From a938c3ef68af249bb3199bde2818436a0bff0952 Mon Sep 17 00:00:00 2001 From: Fabian Guerra Soto Date: Mon, 17 Sep 2018 15:31:43 -0700 Subject: [ios, macos] Offline regions merge. (#12791) * [ios, macos] Add offline regions merge. * [ios, macos] Update changelogs. * [ios, macos] Fix refreshing the offline packs after new content is added. * [ios, macos] Update MGLOfflineStorage's add contents of file documentation. * [ios, macos] Add MGLOfflineStorage test cases for adding file contents. * [ios, macos] Add offline merge test database. * [ios, macos] Add packs parameter to MGLBatchedOfflinePackAdditionCompletionHandler. * [core] Fix a query mege duplication. * [ios, macos] Remove unnecessary pack iteration. * [ios, macos] Fix packs update KVO notifications. * [ios, macos] Add localization strings. * [core] Fix query readability. * [ios, macos] Fix MGLOfflineStorageTest, cleanup the cache database after the test. * [ios, macos] Fix offline packs, updating triggers a crash. --- .../darwin/resources/Base.lproj/Foundation.strings | 3 + platform/darwin/src/MGLOfflineStorage.h | 48 ++++++++ platform/darwin/src/MGLOfflineStorage.mm | 83 ++++++++++++++ platform/darwin/test/MGLOfflineStorageTests.mm | 124 +++++++++++++++++++++ platform/darwin/test/barcelona.db | Bin 0 -> 32391168 bytes platform/default/mbgl/storage/offline_database.cpp | 4 +- platform/ios/CHANGELOG.md | 1 + platform/ios/ios.xcodeproj/project.pbxproj | 6 + .../ios/resources/Base.lproj/Localizable.strings | 6 - platform/macos/CHANGELOG.md | 1 + platform/macos/macos.xcodeproj/project.pbxproj | 4 + 11 files changed, 272 insertions(+), 8 deletions(-) create mode 100644 platform/darwin/test/barcelona.db diff --git a/platform/darwin/resources/Base.lproj/Foundation.strings b/platform/darwin/resources/Base.lproj/Foundation.strings index ba7db3fc63..19bfe750e6 100644 --- a/platform/darwin/resources/Base.lproj/Foundation.strings +++ b/platform/darwin/resources/Base.lproj/Foundation.strings @@ -1,3 +1,6 @@ +/* User-friendly error description */ +"ADD_FILE_CONTENTS_FAILED_DESC" = "Unable to add offline packs from the file at %@."; + /* Clock position format, long: {hours} o’clock */ "CLOCK_FMT_LONG" = "%@ o’clock"; diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h index f8ea6e7453..d512c60845 100644 --- a/platform/darwin/src/MGLOfflineStorage.h +++ b/platform/darwin/src/MGLOfflineStorage.h @@ -134,6 +134,18 @@ typedef void (^MGLOfflinePackAdditionCompletionHandler)(MGLOfflinePack * _Nullab */ typedef void (^MGLOfflinePackRemovalCompletionHandler)(NSError * _Nullable error); +/** + A block to be called once the contents of a file are copied into the current packs. + + @param fileURL The file URL of the offline database containing the offline packs + that were copied. + @param packs An array of all known offline packs, or `nil` if there was an error + creating or adding the pack. + @param error A pointer to an error object (if any) indicating why the pack could + not be created or added. + */ +typedef void (^MGLBatchedOfflinePackAdditionCompletionHandler)(NSURL *fileURL, NSArray * _Nullable packs, NSError * _Nullable error); + /** The type of resource that is requested. */ @@ -174,6 +186,42 @@ MGL_EXPORT */ @property (class, nonatomic, readonly) MGLOfflineStorage *sharedOfflineStorage; +#pragma mark - Adding Contents of File + +/** + Adds the offline packs located at the given file path to offline storage. + + The file must be a valid offline region database bundled with the application + or downloaded separately. + + The resulting packs are added or updated to the shared offline storage object’s `packs` + property, then the `completion` block is executed. + + @param filePath A string representation of the file path. The file path must be + writable as schema updates may be perfomed. + @param completion The completion handler to call once the contents of the given + file has been added to offline storage. This handler is executed asynchronously + on the main queue. + */ +- (void)addContentsOfFile:(NSString *)filePath withCompletionHandler:(nullable MGLBatchedOfflinePackAdditionCompletionHandler)completion; + +/** + Adds the offline packs located at the given URL to offline storage. + + The file must be a valid offline region database bundled with the application + or downloaded separately. + + The resulting packs are added or updated to the shared offline storage object’s `packs` + property, then the `completion` block is executed. + + @param fileURL A file URL specifying the file to add. URL should be a valid system path. + The file URL must be writable as schema updates may be performed. + @param completion The completion handler to call once the contents of the given + file has been added to offline storage. This handler is executed asynchronously + on the main queue. + */ +- (void)addContentsOfURL:(NSURL *)fileURL withCompletionHandler:(nullable MGLBatchedOfflinePackAdditionCompletionHandler)completion; + #pragma mark - Accessing the Delegate /** diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index 93a6da36c4..fd6dd2f998 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -264,6 +264,89 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio } } +#pragma mark Offline merge methods + +- (void)addContentsOfFile:(NSString *)filePath withCompletionHandler:(MGLBatchedOfflinePackAdditionCompletionHandler)completion { + NSURL *fileURL = [NSURL fileURLWithPath:filePath]; + + [self addContentsOfURL:fileURL withCompletionHandler:completion]; + +} + +- (void)addContentsOfURL:(NSURL *)fileURL withCompletionHandler:(MGLBatchedOfflinePackAdditionCompletionHandler)completion { + + NSFileManager *fileManager = [NSFileManager defaultManager]; + + if (!fileURL.isFileURL) { + [NSException raise:NSInvalidArgumentException format:@"%@ must be a valid file path", fileURL.absoluteString]; + } + if (![fileManager isWritableFileAtPath:fileURL.path]) { + [NSException raise:NSInvalidArgumentException format:@"The file path: %@ must be writable", fileURL.absoluteString]; + } + + __weak MGLOfflineStorage *weakSelf = self; + [self _addContentsOfFile:fileURL.path withCompletionHandler:^(NSArray * _Nullable packs, NSError * _Nullable error) { + if (packs) { + NSMutableDictionary *packsByIdentifier = [NSMutableDictionary dictionary]; + + MGLOfflineStorage *strongSelf = weakSelf; + for (MGLOfflinePack *pack in packs) { + [packsByIdentifier setObject:pack forKey:@(pack.mbglOfflineRegion->getID())]; + } + + id mutablePacks = [strongSelf mutableArrayValueForKey:@"packs"]; + NSMutableIndexSet *replaceIndexSet = [NSMutableIndexSet indexSet]; + NSMutableArray *replacePacksArray = [NSMutableArray array]; + [strongSelf.packs enumerateObjectsUsingBlock:^(MGLOfflinePack * _Nonnull pack, NSUInteger idx, BOOL * _Nonnull stop) { + MGLOfflinePack *newPack = packsByIdentifier[@(pack.mbglOfflineRegion->getID())]; + if (newPack) { + MGLOfflinePack *previousPack = [mutablePacks objectAtIndex:idx]; + [previousPack invalidate]; + [replaceIndexSet addIndex:idx]; + [replacePacksArray addObject:[packsByIdentifier objectForKey:@(newPack.mbglOfflineRegion->getID())]]; + [packsByIdentifier removeObjectForKey:@(newPack.mbglOfflineRegion->getID())]; + } + + }]; + + if (replaceIndexSet.count > 0) { + [mutablePacks replaceObjectsAtIndexes:replaceIndexSet withObjects:replacePacksArray]; + } + + [mutablePacks addObjectsFromArray:packsByIdentifier.allValues]; + } + if (completion) { + completion(fileURL, packs, error); + } + }]; +} + +- (void)_addContentsOfFile:(NSString *)filePath withCompletionHandler:(void (^)(NSArray * _Nullable packs, NSError * _Nullable error))completion { + self.mbglFileSource->mergeOfflineRegions(std::string(static_cast([filePath UTF8String])), [&, completion, filePath](mbgl::expected result) { + NSError *error; + NSMutableArray *packs; + if (!result) { + NSString *description = [NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"ADD_FILE_CONTENTS_FAILED_DESC", @"Foundation", nil, @"Unable to add offline packs from the file at %@.", @"User-friendly error description"), filePath]; + error = [NSError errorWithDomain:MGLErrorDomain code:-1 userInfo:@{ + NSLocalizedDescriptionKey: description, + NSLocalizedFailureReasonErrorKey: @(mbgl::util::toString(result.error()).c_str()) + }]; + } else { + auto& regions = result.value(); + packs = [NSMutableArray arrayWithCapacity:regions.size()]; + for (auto ®ion : regions) { + MGLOfflinePack *pack = [[MGLOfflinePack alloc] initWithMBGLRegion:new mbgl::OfflineRegion(std::move(region))]; + [packs addObject:pack]; + } + } + if (completion) { + dispatch_async(dispatch_get_main_queue(), [&, completion, error, packs](void) { + completion(packs, error); + }); + } + }); +} + #pragma mark Pack management methods - (void)addPackForRegion:(id )region withContext:(NSData *)context completionHandler:(MGLOfflinePackAdditionCompletionHandler)completion { diff --git a/platform/darwin/test/MGLOfflineStorageTests.mm b/platform/darwin/test/MGLOfflineStorageTests.mm index e9e2467f21..f89d922f11 100644 --- a/platform/darwin/test/MGLOfflineStorageTests.mm +++ b/platform/darwin/test/MGLOfflineStorageTests.mm @@ -12,6 +12,24 @@ @implementation MGLOfflineStorageTests ++ (void)tearDown { + NSURL *cacheDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSApplicationSupportDirectory + inDomain:NSUserDomainMask + appropriateForURL:nil + create:NO + error:nil]; + // Unit tests don't use the main bundle; use com.mapbox.ios.sdk instead. + NSString *bundleIdentifier = [NSBundle bundleForClass:[MGLMapView class]].bundleIdentifier; + cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:bundleIdentifier]; + cacheDirectoryURL = [cacheDirectoryURL URLByAppendingPathComponent:@".mapbox"]; + XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:cacheDirectoryURL.path], @"Cache subdirectory should exist."); + + NSURL *cacheURL = [cacheDirectoryURL URLByAppendingPathComponent:@"cache.db"]; + + [[NSFileManager defaultManager] removeItemAtURL:cacheURL error:nil]; + XCTAssertFalse([[NSFileManager defaultManager] fileExistsAtPath:cacheURL.path], @"Cache subdirectory should not exist."); +} + - (void)setUp { [super setUp]; @@ -264,4 +282,110 @@ [os setDelegate:nil]; } +- (void)testAddFileContent { + + + // Valid database + { + NSURL *resourceURL = [NSURL fileURLWithPath:[[NSBundle bundleForClass:[self class]] pathForResource:@"barcelona" ofType:@"db"]]; + NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentDir = [documentPaths objectAtIndex:0]; + NSString *filePath = [documentDir stringByAppendingPathComponent:@"barcelona.db"]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + + BOOL exists = [fileManager fileExistsAtPath:filePath]; + if (exists) { + [fileManager removeItemAtPath:filePath error:nil]; + } + + NSError *error; + [fileManager moveItemAtURL:resourceURL toURL:[NSURL fileURLWithPath:filePath] error:&error]; + NSDictionary *atributes = @{ NSFilePosixPermissions: @0777 }; + error = nil; + [fileManager setAttributes:atributes ofItemAtPath:filePath error:&error]; + XCTAssertNil(error, @"Changing the file's permissions:%@ should not return an error.", filePath); + error = nil; + NSDictionary *fileAttributes = [fileManager attributesOfItemAtPath:filePath error:&error]; + + NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize]; + long long fileSize = [fileSizeNumber longLongValue]; + long long dabaseFileSize = 32391168; + // Merging databases creates an empty file if the file does not exist at the given path. + XCTAssertEqual(fileSize, dabaseFileSize, @"The dabase file size must be:%l actual size:%l", dabaseFileSize, fileSize); + + NSUInteger countOfPacks = [MGLOfflineStorage sharedOfflineStorage].packs.count; + + [self keyValueObservingExpectationForObject:[MGLOfflineStorage sharedOfflineStorage] keyPath:@"packs" handler:^BOOL(id _Nonnull observedObject, NSDictionary * _Nonnull change) { + const auto changeKind = static_cast([change[NSKeyValueChangeKindKey] unsignedLongValue]); + NSIndexSet *indices = change[NSKeyValueChangeIndexesKey]; + return changeKind == NSKeyValueChangeInsertion && indices.count == 1; + }]; + + XCTestExpectation *fileAdditionCompletionHandlerExpectation = [self expectationWithDescription:@"add database content completion handler"]; + MGLOfflineStorage *os = [MGLOfflineStorage sharedOfflineStorage]; + [os addContentsOfFile:filePath withCompletionHandler:^(NSURL *fileURL, NSArray * _Nullable packs, NSError * _Nullable error) { + XCTAssertNotNil(fileURL, @"The fileURL should not be nil."); + XCTAssertNotNil(packs, @"Adding the contents of the barcelona.db should update one pack."); + XCTAssertNil(error, @"Adding contents to a file should not return an error."); + for (MGLOfflinePack *pack in [MGLOfflineStorage sharedOfflineStorage].packs) { + NSLog(@"PACK:%@", pack); + } + [fileAdditionCompletionHandlerExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:2 handler:nil]; + // Depending on the database it may update or add a pack. For this case specifically the offline database adds one pack. + XCTAssertEqual([MGLOfflineStorage sharedOfflineStorage].packs.count, countOfPacks + 1, @"Adding contents of barcelona.db should add one pack."); + } + // Invalid database type + { + NSURL *resourceURL = [NSURL fileURLWithPath:[[NSBundle bundleForClass:[self class]] pathForResource:@"one-liner" ofType:@"json"]]; + NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentDir = [documentPaths objectAtIndex:0]; + NSString *filePath = [documentDir stringByAppendingPathComponent:@"on-liner-copy.json"]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + + BOOL exists = [fileManager fileExistsAtPath:filePath]; + if (exists) { + [fileManager removeItemAtPath:filePath error:nil]; + } + + NSError *error; + [fileManager copyItemAtURL:resourceURL toURL:[NSURL fileURLWithPath:filePath] error:&error]; + + XCTestExpectation *invalidFileCompletionHandlerExpectation = [self expectationWithDescription:@"invalid content database completion handler"]; + MGLOfflineStorage *os = [MGLOfflineStorage sharedOfflineStorage]; + [os addContentsOfFile:filePath withCompletionHandler:^(NSURL *fileURL, NSArray * _Nullable packs, NSError * _Nullable error) { + XCTAssertNotNil(error, @"Passing an invalid offline database file should return an error."); + XCTAssertNil(packs, @"Passing an invalid offline database file should not add packs to the offline database."); + [invalidFileCompletionHandlerExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:2 handler:nil]; + } + // File non existent + { + NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentDir = [documentPaths objectAtIndex:0]; + NSString *filePath = [documentDir stringByAppendingPathComponent:@"nonexistent.db"]; + NSFileManager *fileManager = [NSFileManager defaultManager]; + + BOOL exists = [fileManager fileExistsAtPath:filePath]; + if (exists) { + [fileManager removeItemAtPath:filePath error:nil]; + } + + MGLOfflineStorage *os = [MGLOfflineStorage sharedOfflineStorage]; + XCTAssertThrowsSpecificNamed([os addContentsOfFile:filePath withCompletionHandler:nil], NSException, NSInvalidArgumentException, "MGLOfflineStorage should rise an exception if an invalid database file is passed."); + + } + // URL to a non-file + { + NSURL *resourceURL = [NSURL URLWithString:@"https://www.mapbox.com"]; + + MGLOfflineStorage *os = [MGLOfflineStorage sharedOfflineStorage]; + XCTAssertThrowsSpecificNamed([os addContentsOfURL:resourceURL withCompletionHandler:nil], NSException, NSInvalidArgumentException, "MGLOfflineStorage should rise an exception if an invalid URL file is passed."); + + } + +} + @end diff --git a/platform/darwin/test/barcelona.db b/platform/darwin/test/barcelona.db new file mode 100644 index 0000000000..a3c2284202 Binary files /dev/null and b/platform/darwin/test/barcelona.db differ diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp index 37490d2f6f..28c1359106 100644 --- a/platform/default/mbgl/storage/offline_database.cpp +++ b/platform/default/mbgl/storage/offline_database.cpp @@ -689,9 +689,9 @@ OfflineDatabase::mergeDatabase(const std::string& sideDatabasePath) { // clang-format off mapbox::sqlite::Query queryRegions{ getStatement( - "SELECT r.id, r.definition, r.description " + "SELECT DISTINCT r.id, r.definition, r.description " "FROM side.regions sr " - "JOIN regions r ON sr.definition = r.definition") }; + "JOIN regions r ON sr.definition = r.definition AND sr.description IS r.description") }; // clang-format on OfflineRegions result; diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index c98fc4b71c..ab0a6f6193 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -36,6 +36,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT * Added the `MGLShapeOfflineRegion` class for creating an offline pack that covers an arbitrary shape. ([#11447](https://github.com/mapbox/mapbox-gl-native/pull/11447)) * Fixed crashes when offline storage encountered certain SQLite errors. ([#12224](https://github.com/mapbox/mapbox-gl-native/pull/12224)) +* Added `-[MGLOfflineStorage addContentsOfFile:withCompletionHandler:]` and `-[MGLOfflineStorage addContentsOfURL:withCompletionHandler:]` methods to add pregenerated offline packs to offline storage. ([#12791](https://github.com/mapbox/mapbox-gl-native/pull/12791)) ### Other changes diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index 5c42d4aada..960fc4161b 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -33,6 +33,8 @@ 1F06668D1EC64F8E001C16D7 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F0666891EC64F8E001C16D7 /* MGLLight.mm */; }; 1F26B6C120E189C9007BCC21 /* MBXCustomLocationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F26B6C020E189C9007BCC21 /* MBXCustomLocationViewController.m */; }; 1F26B6C320E1A351007BCC21 /* simple_route.json in Resources */ = {isa = PBXBuildFile; fileRef = 1F26B6C220E1A351007BCC21 /* simple_route.json */; }; + 1F5627F62148387100038ED1 /* barcelona.db in Resources */ = {isa = PBXBuildFile; fileRef = 1F5627F52148387100038ED1 /* barcelona.db */; }; + 1F5627F72148387100038ED1 /* barcelona.db in Resources */ = {isa = PBXBuildFile; fileRef = 1F5627F52148387100038ED1 /* barcelona.db */; }; 1F7454921ECBB42C00021D39 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F0666891EC64F8E001C16D7 /* MGLLight.mm */; }; 1F7454931ECBB43F00021D39 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1F7454961ECD450D00021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454941ECD450D00021D39 /* MGLLight_Private.h */; }; @@ -782,6 +784,7 @@ 1F26B6BF20E189C9007BCC21 /* MBXCustomLocationViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MBXCustomLocationViewController.h; sourceTree = ""; }; 1F26B6C020E189C9007BCC21 /* MBXCustomLocationViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBXCustomLocationViewController.m; sourceTree = ""; }; 1F26B6C220E1A351007BCC21 /* simple_route.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = simple_route.json; sourceTree = ""; }; + 1F5627F52148387100038ED1 /* barcelona.db */ = {isa = PBXFileReference; lastKnownFileType = file; name = barcelona.db; path = ../../darwin/test/barcelona.db; sourceTree = ""; }; 1F7454941ECD450D00021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = ""; }; 1F7454A61ED08AB400021D39 /* MGLLightTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLLightTest.mm; path = ../../darwin/test/MGLLightTest.mm; sourceTree = ""; }; 1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLNSDateAdditionsTests.mm; path = ../../darwin/test/MGLNSDateAdditionsTests.mm; sourceTree = ""; }; @@ -1922,6 +1925,7 @@ DA2E88551CC036F400F24E7B /* Info.plist */, DA2784FB1DF02FF4001D5B8D /* Media.xcassets */, DA35D0871E1A6309007DED41 /* one-liner.json */, + 1F5627F52148387100038ED1 /* barcelona.db */, ); name = "SDK Tests"; path = test; @@ -2795,6 +2799,7 @@ buildActionMask = 2147483647; files = ( 16376B471FFDB92B0000563E /* one-liner.json in Resources */, + 1F5627F72148387100038ED1 /* barcelona.db in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2843,6 +2848,7 @@ DA2784FC1DF02FF4001D5B8D /* Media.xcassets in Resources */, 353BAEF71D646370009A8DA9 /* amsterdam.geojson in Resources */, DA35D0881E1A6309007DED41 /* one-liner.json in Resources */, + 1F5627F62148387100038ED1 /* barcelona.db in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/platform/ios/resources/Base.lproj/Localizable.strings b/platform/ios/resources/Base.lproj/Localizable.strings index 571a6bca6b..d660cb6ddd 100644 --- a/platform/ios/resources/Base.lproj/Localizable.strings +++ b/platform/ios/resources/Base.lproj/Localizable.strings @@ -1,12 +1,6 @@ /* Accessibility hint */ "ANNOTATION_A11Y_HINT" = "Shows more info"; -/* No comment provided by engineer. */ -"API_CLIENT_400_DESC" = "The session data task failed. Original request was: %@"; - -/* No comment provided by engineer. */ -"API_CLIENT_400_REASON" = "The status code was %ld"; - /* No comment provided by engineer. */ "CANCEL" = "Cancel"; diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md index fcac5c18c3..e51a3bca95 100644 --- a/platform/macos/CHANGELOG.md +++ b/platform/macos/CHANGELOG.md @@ -30,6 +30,7 @@ * Added the `MGLShapeOfflineRegion` class for creating an offline pack that covers an arbitrary shape. ([#11447](https://github.com/mapbox/mapbox-gl-native/pull/11447)) * Fixed crashes when offline storage encountered certain SQLite errors. ([#12224](https://github.com/mapbox/mapbox-gl-native/pull/12224)) +* Added `-[MGLOfflineStorage addContentsOfFile:withCompletionHandler:]` and `-[MGLOfflineStorage addContentsOfURL:withCompletionHandler:]` methods to add pregenerated offline packs to offline storage. ([#12791](https://github.com/mapbox/mapbox-gl-native/pull/12791)) ### Other changes diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj index 040bd785d5..6fb5dff34a 100644 --- a/platform/macos/macos.xcodeproj/project.pbxproj +++ b/platform/macos/macos.xcodeproj/project.pbxproj @@ -18,6 +18,7 @@ 170A82BF201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170A82BE201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm */; }; 170A82C4201FB6EC00943087 /* MGLHeatmapColorTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170A82C2201FAFF800943087 /* MGLHeatmapColorTests.mm */; }; 1753ED401E53CE6100A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */; }; + 1F5627F9214838A300038ED1 /* barcelona.db in Resources */ = {isa = PBXBuildFile; fileRef = 1F5627F8214838A200038ED1 /* barcelona.db */; }; 1F7454A31ECFB00300021D39 /* MGLLight_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */; }; 1F7454A41ECFB00300021D39 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F7454A11ECFB00300021D39 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F7454A21ECFB00300021D39 /* MGLLight.mm */; }; @@ -311,6 +312,7 @@ 170A82BE201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLHeatmapStyleLayerTests.mm; sourceTree = ""; }; 170A82C2201FAFF800943087 /* MGLHeatmapColorTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLHeatmapColorTests.mm; sourceTree = ""; }; 1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = ""; }; + 1F5627F8214838A200038ED1 /* barcelona.db */ = {isa = PBXFileReference; lastKnownFileType = file; name = barcelona.db; path = ../../darwin/test/barcelona.db; sourceTree = ""; }; 1F7454A01ECFB00300021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = ""; }; 1F7454A11ECFB00300021D39 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = ""; }; 1F7454A21ECFB00300021D39 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = ""; }; @@ -1125,6 +1127,7 @@ DAE6C33A1CC30DB200DB3429 /* Info.plist */, DA2784FD1DF03060001D5B8D /* Media.xcassets */, DA35D0891E1A631B007DED41 /* one-liner.json */, + 1F5627F8214838A200038ED1 /* barcelona.db */, ); name = "SDK Tests"; path = test; @@ -1500,6 +1503,7 @@ 35724FC41D630502002A4AB4 /* amsterdam.geojson in Resources */, DA2784FE1DF03060001D5B8D /* Media.xcassets in Resources */, DA35D08A1E1A631B007DED41 /* one-liner.json in Resources */, + 1F5627F9214838A300038ED1 /* barcelona.db in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; -- cgit v1.2.1