diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2016-03-10 16:55:04 -0800 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2016-03-10 17:14:14 -0800 |
commit | 641c31507d282322469e0b05fdde5df11bd66128 (patch) | |
tree | 98c37f76a1dbc38d4ec481734971c757ae14be06 /platform/ios/app/MBXOfflinePacksTableViewController.m | |
parent | ff9c3a57b05fa3287a126ffd7c66cddc7e0929dc (diff) | |
download | qtlocation-mapboxgl-641c31507d282322469e0b05fdde5df11bd66128.tar.gz |
[ios] Renamed downloads to offline packs in iosapp
Diffstat (limited to 'platform/ios/app/MBXOfflinePacksTableViewController.m')
-rw-r--r-- | platform/ios/app/MBXOfflinePacksTableViewController.m | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/platform/ios/app/MBXOfflinePacksTableViewController.m b/platform/ios/app/MBXOfflinePacksTableViewController.m new file mode 100644 index 0000000000..32e4bfea06 --- /dev/null +++ b/platform/ios/app/MBXOfflinePacksTableViewController.m @@ -0,0 +1,229 @@ +#import "MBXOfflinePacksTableViewController.h" + +#import <Mapbox/Mapbox.h> + +static NSString * const MBXOfflinePackContextNameKey = @"Name"; + +static NSString * const MBXOfflinePacksTableViewInactiveCellReuseIdentifier = @"Inactive"; +static NSString * const MBXOfflinePacksTableViewActiveCellReuseIdentifier = @"Active"; + +@implementation MGLOfflinePack (MBXAdditions) + +- (NSString *)name { + NSDictionary *userInfo = [NSKeyedUnarchiver unarchiveObjectWithData:self.context]; + NSAssert([userInfo isKindOfClass:[NSDictionary class]], @"Context of offline pack isn’t a dictionary."); + NSString *name = userInfo[MBXOfflinePackContextNameKey]; + NSAssert([name isKindOfClass:[NSString class]], @"Name of offline pack isn’t a string."); + return name; +} + +@end + +@implementation MGLTilePyramidOfflineRegion (MBXAdditions) + +- (void)applyToMapView:(MGLMapView *)mapView { + mapView.styleURL = self.styleURL; + [mapView setVisibleCoordinateBounds:self.bounds]; +} + +@end + +@interface MBXOfflinePacksTableViewController () <MGLOfflinePackDelegate> + +@property (nonatomic, strong) NS_MUTABLE_ARRAY_OF(MGLOfflinePack *) *offlinePacks; + +@end + +@implementation MBXOfflinePacksTableViewController { + NSUInteger _untitledRegionCount; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + __weak MBXOfflinePacksTableViewController *weakSelf = self; + [[MGLOfflineStorage sharedOfflineStorage] getPacksWithCompletionHandler:^(NS_ARRAY_OF(MGLOfflinePack *) *packs, NSError *error) { + MBXOfflinePacksTableViewController *strongSelf = weakSelf; + strongSelf.offlinePacks = packs.mutableCopy; + [strongSelf.tableView reloadData]; + + for (MGLOfflinePack *pack in strongSelf.offlinePacks) { + pack.delegate = strongSelf; + [pack requestProgress]; + } + + if (error) { + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Can’t Find Offline Packs" message:@"Mapbox GL was unable to find the existing offline packs." preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alertController animated:YES completion:^{ + [strongSelf dismissViewControllerAnimated:YES completion:nil]; + }]; + } + }]; +} + +- (IBAction)addCurrentRegion:(id)sender { + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Add Offline Pack" message:@"Choose a name for the pack:" preferredStyle:UIAlertControllerStyleAlert]; + [alertController addTextFieldWithConfigurationHandler:nil]; + [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + + UIAlertAction *downloadAction = [UIAlertAction actionWithTitle:@"Download" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + MGLMapView *mapView = self.mapView; + NSAssert(mapView, @"No map view to get the current region from."); + + NSString *name = alertController.textFields.firstObject.text; + if (!name.length) { + name = [NSString stringWithFormat:@"Untitled %lu", (unsigned long)++_untitledRegionCount]; + } + + MGLTilePyramidOfflineRegion *region = [[MGLTilePyramidOfflineRegion alloc] initWithStyleURL:mapView.styleURL bounds:mapView.visibleCoordinateBounds fromZoomLevel:mapView.zoomLevel toZoomLevel:mapView.maximumZoomLevel]; + NSData *context = [NSKeyedArchiver archivedDataWithRootObject:@{ + MBXOfflinePackContextNameKey: name, + }]; + + __weak MBXOfflinePacksTableViewController *weakSelf = self; + [[MGLOfflineStorage sharedOfflineStorage] addPackForRegion:region withContext:context completionHandler:^(MGLOfflinePack *pack, NSError *error) { + MBXOfflinePacksTableViewController *strongSelf = weakSelf; + if (error) { + NSString *message = [NSString stringWithFormat:@"Mapbox GL was unable to add the offline pack “%@”.", name]; + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Can’t Add Offline Pack" message:message preferredStyle:UIAlertControllerStyleAlert]; + [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]]; + [self presentViewController:alertController animated:YES completion:nil]; + } else { + pack.delegate = strongSelf; + [pack resume]; + + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:strongSelf.offlinePacks.count inSection:0]; + [strongSelf.offlinePacks addObject:pack]; + [strongSelf.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + } + }]; + }]; + [alertController addAction:downloadAction]; + alertController.preferredAction = downloadAction; + + [self presentViewController:alertController animated:YES completion:nil]; +} + +#pragma mark - Table view data source + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.offlinePacks.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + MGLOfflinePack *pack = self.offlinePacks[indexPath.row]; + + NSString *reuseIdentifier = pack.state == MGLOfflinePackStateActive ? MBXOfflinePacksTableViewActiveCellReuseIdentifier : MBXOfflinePacksTableViewInactiveCellReuseIdentifier; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath]; + cell.textLabel.text = pack.name; + MGLOfflinePackProgress progress = pack.progress; + NSString *completedString = [NSNumberFormatter localizedStringFromNumber:@(progress.countOfResourcesCompleted) + numberStyle:NSNumberFormatterDecimalStyle]; + NSString *expectedString = [NSNumberFormatter localizedStringFromNumber:@(progress.countOfResourcesExpected) + numberStyle:NSNumberFormatterDecimalStyle]; + NSString *byteCountString = [NSByteCountFormatter stringFromByteCount:progress.countOfBytesCompleted + countStyle:NSByteCountFormatterCountStyleFile]; + NSString *statusString; + switch (pack.state) { + case MGLOfflinePackStateUnknown: + statusString = @"Calculating progress…"; + break; + + case MGLOfflinePackStateInactive: + statusString = [NSString stringWithFormat:@"%@ of %@ resources (%@)", + completedString, expectedString, byteCountString]; + break; + + case MGLOfflinePackStateComplete: + statusString = [NSString stringWithFormat:@"%@ resources (%@)", + completedString, byteCountString]; + break; + + case MGLOfflinePackStateActive: + if (progress.countOfResourcesExpected) { + completedString = [NSNumberFormatter localizedStringFromNumber:@(progress.countOfResourcesCompleted + 1) + numberStyle:NSNumberFormatterDecimalStyle]; + } + if (progress.maximumResourcesExpected > progress.countOfResourcesExpected) { + expectedString = [@"at least " stringByAppendingString:expectedString]; + } + statusString = [NSString stringWithFormat:@"Downloading %@ of %@ resources (%@ so far)…", + completedString, expectedString, byteCountString]; + break; + + case MGLOfflinePackStateInvalid: + NSAssert(NO, @"Invalid offline pack at index path %@", indexPath); + break; + } + cell.detailTextLabel.text = statusString; + + return cell; +} + +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + if (editingStyle == UITableViewCellEditingStyleDelete) { + MGLOfflinePack *pack = self.offlinePacks[indexPath.row]; + __weak MBXOfflinePacksTableViewController *weakSelf = self; + [[MGLOfflineStorage sharedOfflineStorage] removePack:pack withCompletionHandler:^(NSError *error) { + MBXOfflinePacksTableViewController *strongSelf = weakSelf; + [strongSelf.offlinePacks removeObjectAtIndex:indexPath.row]; + [strongSelf.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + }]; + } +} + +#pragma mark - Table view delegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; + + MGLOfflinePack *pack = self.offlinePacks[indexPath.row]; + switch (pack.state) { + case MGLOfflinePackStateUnknown: + break; + + case MGLOfflinePackStateComplete: + if ([pack.region respondsToSelector:@selector(applyToMapView:)]) { + [pack.region performSelector:@selector(applyToMapView:) withObject:self.mapView]; + } + [self performSegueWithIdentifier:@"ReturnToMap" sender:self]; + break; + + case MGLOfflinePackStateInactive: + [pack resume]; + [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + break; + + case MGLOfflinePackStateActive: + [pack suspend]; + [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + break; + + case MGLOfflinePackStateInvalid: + NSAssert(NO, @"Invalid offline pack at index path %@", indexPath); + break; + } +} + +#pragma mark - Offline pack delegate + +- (void)offlinePack:(MGLOfflinePack *)pack progressDidChange:(MGLOfflinePackProgress)progress { + NSUInteger index = [self.offlinePacks indexOfObject:pack]; + if (index == NSNotFound) { + return; + } + + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0]; + [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; +} + +- (void)offlinePack:(MGLOfflinePack *)pack didReceiveError:(NSError *)error { + NSLog(@"Offline pack “%@” received error: %@", pack.name, error.localizedFailureReason); +} + +- (void)offlinePack:(MGLOfflinePack *)pack didReceiveMaximumAllowedMapboxTiles:(uint64_t)maximumCount { + NSLog(@"Offline pack “%@” reached limit of %llu tiles.", pack.name, maximumCount); +} + +@end |