Skip to content

Commit

Permalink
Call requestProgress when getting pack status on IOS + example improv…
Browse files Browse the repository at this point in the history
…ement (#445)

* migrate CreateOfflineRegion example to TypeScript
* update CreateOfflineRegion example
* [IOS] call requestProgress when getting pack status
* update changelog and test
* Update yarn.lock
  • Loading branch information
caspg authored Oct 10, 2024
1 parent 2202908 commit 300ad8f
Show file tree
Hide file tree
Showing 11 changed files with 342 additions and 242 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fix: [disable code signing for release builds](<[#450](https://github.com/maplib
fix: [disable library code signing](<[#447](https://github.com/maplibre/maplibre-react-native/pull/447)>)

feat: [feat: yarn monorepo](<[#441](https://github.com/maplibre/maplibre-react-native/pull/441)>)
fix: Call requestProgress when getting pack status on IOS + example improvement [#445](https://github.com/maplibre/maplibre-react-native/pull/445)

## 10.0.0-alpha.13

Expand Down
1 change: 1 addition & 0 deletions __tests__/interface.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('Public Interface', () => {
// modules
'offlineManager',
'OfflineCreatePackOptions',
'OfflinePack',
'snapshotManager',
'locationManager',

Expand Down
101 changes: 61 additions & 40 deletions ios/RCTMLN/MLNOfflineModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ - (instancetype)init
packRequestQueue = [NSMutableArray new];
eventThrottle = 300;
lastPackState = -1;

NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self selector:@selector(offlinePackProgressDidChange:) name:MLNOfflinePackProgressChangedNotification object:nil];
[defaultCenter addObserver:self selector:@selector(offlinePackDidReceiveError:) name:MLNOfflinePackErrorNotification object:nil];
[defaultCenter addObserver:self selector:@selector(offlinePackDidReceiveMaxAllowedMapboxTiles:) name:MLNOfflinePackMaximumMapboxTilesReachedNotification object:nil];

[[MLNOfflineStorage sharedOfflineStorage] addObserver:self forKeyPath:@"packs" options:NSKeyValueObservingOptionInitial context:NULL];
}
return self;
Expand All @@ -72,15 +72,21 @@ - (void)dealloc

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"state"] && [object isKindOfClass:[MLNOfflinePack class]]) {
MLNOfflinePack* pack = (MLNOfflinePack*)object;
[self observerStateForPack:pack context:context];
return;
}

if (packRequestQueue.count == 0) {
return;
}

NSArray<MLNOfflinePack *> *packs = [[MLNOfflineStorage sharedOfflineStorage] packs];
if (packs == nil) {
return;
}

while (packRequestQueue.count > 0) {
RCTPromiseResolveBlock resolve = [packRequestQueue objectAtIndex:0];
resolve([self _convertPacksToJson:packs]);
Expand All @@ -94,13 +100,13 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
{
NSString *styleURL = options[@"styleURL"];
MLNCoordinateBounds bounds = [RCTMLNUtils fromFeatureCollection:options[@"bounds"]];

id<MLNOfflineRegion> offlineRegion = [[MLNTilePyramidOfflineRegion alloc] initWithStyleURL:[NSURL URLWithString:styleURL]
bounds:bounds
fromZoomLevel:[options[@"minZoom"] doubleValue]
toZoomLevel:[options[@"maxZoom"] doubleValue]];
NSData *context = [self _archiveMetadata:options[@"metadata"]];

[[MLNOfflineStorage sharedOfflineStorage] addPackForRegion:offlineRegion
withContext:context
completionHandler:^(MLNOfflinePack *pack, NSError *error) {
Expand Down Expand Up @@ -129,7 +135,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
return reject(@"asset_does_not_exist", [NSString stringWithFormat:@"The given assetName, %@, can't be found in the app's bundle.", path], nil);
}
}

[[MLNOfflineStorage sharedOfflineStorage] addContentsOfFile:absolutePath withCompletionHandler:^(NSURL *fileURL, NSArray<MLNOfflinePack *> *packs, NSError *error) {
if (error != nil) {
reject(@"mergeOfflineRegions", error.description, error);
Expand All @@ -143,7 +149,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
{
dispatch_async(dispatch_get_main_queue(), ^{
NSArray<MLNOfflinePack *> *packs = [[MLNOfflineStorage sharedOfflineStorage] packs];

if (packs == nil) {
// packs have not loaded yet
[self->packRequestQueue addObject:resolve];
Expand Down Expand Up @@ -187,7 +193,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
}
resolve(nil);
}];

}

RCT_EXPORT_METHOD(resetDatabase:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
Expand All @@ -199,22 +205,37 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
}
resolve(nil);
}];

}

RCT_EXPORT_METHOD(getPackStatus:(NSString *)name
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
MLNOfflinePack *pack = [self _getPackFromName:name];

if (pack == nil) {
resolve(nil);
NSLog(@"getPackStatus - Unknown offline region");
return;
}

resolve([self _makeRegionStatusPayload:name pack:pack]);

if (pack.state == MLNOfflinePackStateUnknown) {
[pack addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:(__bridge_retained void*)resolve];
[pack requestProgress];
} else {
resolve([self _makeRegionStatusPayload:name pack:pack]);
}
}

-(void)observerStateForPack:(MLNOfflinePack*)pack context:(nullable void*) context {
RCTPromiseResolveBlock resolve = (__bridge_transfer RCTPromiseResolveBlock)context;
dispatch_async(dispatch_get_main_queue(), ^{
NSDictionary* metadata = [self _unarchiveMetadata:pack];
NSString* name = metadata[@"name"];
resolve([self _makeRegionStatusPayload:name pack:pack]);
});
[pack removeObserver:self forKeyPath:@"state" context:context];
}

RCT_EXPORT_METHOD(invalidatePack:(NSString *)name
Expand All @@ -241,7 +262,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
rejecter:(RCTPromiseRejectBlock)reject)
{
MLNOfflinePack *pack = [self _getPackFromName:name];

if (pack == nil) {
resolve(nil);
return;
Expand All @@ -265,17 +286,17 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
rejecter:(RCTPromiseRejectBlock)reject)
{
MLNOfflinePack *pack = [self _getPackFromName:name];

if (pack == nil) {
reject(@"pausePackDownload", @"Unknown offline region", nil);
return;
}

if (pack.state == MLNOfflinePackStateInactive || pack.state == MLNOfflinePackStateComplete) {
resolve(nil);
return;
}

[pack suspend];
resolve(nil);
}
Expand All @@ -285,17 +306,17 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
rejecter:(RCTPromiseRejectBlock)reject)
{
MLNOfflinePack *pack = [self _getPackFromName:name];

if (pack == nil) {
reject(@"resumePack", @"Unknown offline region", nil);
return;
}

if (pack.state == MLNOfflinePackStateActive || pack.state == MLNOfflinePackStateComplete) {
resolve(nil);
return;
}

[pack resume];
resolve(nil);
}
Expand All @@ -313,18 +334,18 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
- (void)offlinePackProgressDidChange:(NSNotification *)notification
{
MLNOfflinePack *pack = notification.object;

if (pack.state == MLNOfflinePackStateInvalid) {
return; // Avoid invalid offline pack exception
}

if ([self _shouldSendProgressEvent:[self _getCurrentTimestamp] pack:pack]) {
NSDictionary *metadata = [self _unarchiveMetadata:pack];
RCTMLNEvent *event = [self _makeProgressEvent:metadata[@"name"] pack:pack];
[self _sendEvent:RCT_MAPBOX_OFFLINE_CALLBACK_PROGRESS event:event];
lastPackTimestamp = [self _getCurrentTimestamp];
}

lastPackState = pack.state;
}

Expand All @@ -335,7 +356,7 @@ - (void)offlinePackDidReceiveError:(NSNotification *)notification
return; // Avoid invalid offline pack exception
}
NSDictionary *metadata = [self _unarchiveMetadata:pack];

NSString *name = metadata[@"name"];
if (name != nil) {
NSError *error = notification.userInfo[MLNOfflinePackUserInfoKeyError];
Expand All @@ -350,7 +371,7 @@ - (void)offlinePackDidReceiveMaxAllowedMapboxTiles:(NSNotification *)notificatio
{
MLNOfflinePack *pack = notification.object;
NSDictionary *metadata = [self _unarchiveMetadata:pack];

NSString *name = metadata[@"name"];
if (name != nil) {
RCTMLNEvent *event = [self _makeErrorEvent:name
Expand Down Expand Up @@ -386,11 +407,11 @@ - (NSDictionary *)_unarchiveMetadata:(MLNOfflinePack *)pack
if ([data isKindOfClass:[NSDictionary class]]) {
return data;
}

if (data == nil) {
return @{};
}

return [NSJSONSerialization JSONObjectWithData:[data dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error:nil];
Expand All @@ -406,7 +427,7 @@ - (NSDictionary *)_makeRegionStatusPayload:(NSString *)name pack:(MLNOfflinePack
if(expectedResources == 0) {
progressPercentage = 0;
}

return @{
@"state": @(pack.state),
@"name": name,
Expand All @@ -433,15 +454,15 @@ - (RCTMLNEvent *)_makeErrorEvent:(NSString *)name type:(NSString *)type message:
- (NSArray<NSDictionary *> *)_convertPacksToJson:(NSArray<MLNOfflinePack *> *)packs
{
NSMutableArray<NSDictionary *> *jsonPacks = [NSMutableArray new];

if (packs == nil) {
return jsonPacks;
}

for (MLNOfflinePack *pack in packs) {
[jsonPacks addObject:[self _convertPackToDict:pack]];
}

return jsonPacks;
}

Expand All @@ -452,12 +473,12 @@ - (NSDictionary *)_convertPackToDict:(MLNOfflinePack *)pack
if (region == nil) {
return nil;
}

NSArray *jsonBounds = @[
@[@(region.bounds.ne.longitude), @(region.bounds.ne.latitude)],
@[@(region.bounds.sw.longitude), @(region.bounds.sw.latitude)]
];

// format metadata
NSDictionary *metadata = [self _unarchiveMetadata:pack];
NSData *jsonMetadata = [NSJSONSerialization dataWithJSONObject:metadata
Expand All @@ -472,19 +493,19 @@ - (NSDictionary *)_convertPackToDict:(MLNOfflinePack *)pack
- (MLNOfflinePack *)_getPackFromName:(NSString *)name
{
NSArray<MLNOfflinePack *> *packs = [[MLNOfflineStorage sharedOfflineStorage] packs];

if (packs == nil) {
return nil;
}

for (MLNOfflinePack *pack in packs) {
NSDictionary *metadata = [self _unarchiveMetadata:pack];

if ([name isEqualToString:metadata[@"name"]]) {
return pack;
}
}

return nil;
}

Expand All @@ -501,15 +522,15 @@ - (BOOL)_shouldSendProgressEvent:(double)currentTimestamp pack:(MLNOfflinePack *
if (lastPackState == -1) {
return YES;
}

if (lastPackState != currentPack.state) {
return YES;
}

if (currentTimestamp - lastPackTimestamp > eventThrottle) {
return YES;
}

return NO;
}

Expand Down
6 changes: 6 additions & 0 deletions javascript/Maplibre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ export {
type Location,
} from "./modules/location/locationManager";
export { default as offlineManager } from "./modules/offline/offlineManager";
export type {
OfflineProgressStatus,
OfflinePackError,
} from "./modules/offline/offlineManager";
export type { OfflinePackStatus } from "./modules/offline/OfflinePack";
export { default as OfflinePack } from "./modules/offline/OfflinePack";
export { default as OfflineCreatePackOptions } from "./modules/offline/OfflineCreatePackOptions";
export { default as snapshotManager } from "./modules/snapshot/snapshotManager";
export type { SnapshotInputOptions } from "./modules/snapshot/SnapshotOptions";
Expand Down
2 changes: 1 addition & 1 deletion javascript/modules/offline/OfflinePack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import OfflineCreatePackOptions from "./OfflineCreatePackOptions";

const MapLibreGLOfflineManager = NativeModules.MLNOfflineModule;

type OfflinePackStatus = {
export type OfflinePackStatus = {
name: string;
state: number;
percentage: number;
Expand Down
Loading

0 comments on commit 300ad8f

Please sign in to comment.