diff --git a/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.h b/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.h index af727a6b49..8c194ee101 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.h +++ b/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.h @@ -12,6 +12,7 @@ @class HotelRooms; @class UgcData; @class ElevationProfileData; +@class MWMMapNodeAttributes; typedef NS_ENUM(NSInteger, PlacePageSponsoredType) { PlacePageSponsoredTypeNone, @@ -58,6 +59,7 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly, nullable) HotelRooms *hotelRooms; @property(nonatomic, readonly, nullable) UgcData *ugcData; @property(nonatomic, readonly, nullable) ElevationProfileData *elevationProfileData; +@property(nonatomic, readonly) MWMMapNodeAttributes *mapNodeAttributes; @property(nonatomic, readonly, nullable) NSString *bookingSearchUrl; @property(nonatomic, readonly) BOOL isLargeToponim; @property(nonatomic, readonly) BOOL isSightseeing; @@ -79,6 +81,8 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly, nullable) NSString *sponsoredReviewURL; @property(nonatomic, readonly, nullable) NSString *sponsoredDeeplink; @property(nonatomic, copy, nullable) MWMVoidBlock onBookmarkStatusUpdate; +@property(nonatomic, copy, nullable) MWMVoidBlock onMapNodeStatusUpdate; +@property(nonatomic, copy, nullable) void (^onMapNodeProgressUpdate)(uint64_t downloadedBytes, uint64_t totalBytes); - (instancetype)initWithLocalizationProvider:(id)localization; - (instancetype)init NS_UNAVAILABLE; diff --git a/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm b/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm index a475e5315f..eb0552f291 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm +++ b/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm @@ -9,6 +9,7 @@ #import "HotelRooms+Core.h" #import "UgcData+Core.h" #import "ElevationProfileData+Core.h" +#import "MWMMapNodeAttributes.h" #include #include "platform/network_policy.hpp" @@ -64,6 +65,10 @@ static PlacePageRoadType convertRoadType(RoadWarningMarkType roadType) { } } +@interface PlacePageData () + +@end + @implementation PlacePageData - (instancetype)initWithLocalizationProvider:(id)localization { @@ -125,11 +130,17 @@ static PlacePageRoadType convertRoadType(RoadWarningMarkType roadType) { _sponsoredDeeplink = @(rawData().GetSponsoredDeepLink().c_str()); } + _mapNodeAttributes = [[MWMStorage sharedStorage] attributesForCountry:@(rawData().GetCountryId().c_str())]; + [[MWMStorage sharedStorage] addObserver:self]; // _elevationProfileData = [[ElevationProfileData alloc] init]; } return self; } +- (void)dealloc { + [[MWMStorage sharedStorage] removeObserver:self]; +} + - (void)loadOnlineDataWithCompletion:(MWMVoidBlock)completion { dispatch_group_t group = dispatch_group_create(); if (self.previewData.isBookingPlace) { @@ -270,4 +281,21 @@ static PlacePageRoadType convertRoadType(RoadWarningMarkType roadType) { } } +#pragma mark - MWMStorageObserver + +- (void)processCountryEvent:(NSString *)countryId { + if ([countryId isEqualToString:self.mapNodeAttributes.countryId]) { + _mapNodeAttributes = [[MWMStorage sharedStorage] attributesForCountry:@(rawData().GetCountryId().c_str())]; + if (self.onMapNodeStatusUpdate != nil) { + self.onMapNodeStatusUpdate(); + } + } +} + +- (void)processCountry:(NSString *)countryId downloadedBytes:(uint64_t)downloadedBytes totalBytes:(uint64_t)totalBytes { + if ([countryId isEqualToString:self.mapNodeAttributes.countryId] && self.onMapNodeProgressUpdate != nil) { + self.onMapNodeProgressUpdate(downloadedBytes, totalBytes); + } +} + @end diff --git a/iphone/CoreApi/CoreApi/Storage/MWMMapNodeAttributes.h b/iphone/CoreApi/CoreApi/Storage/MWMMapNodeAttributes.h index 72fb64d8fc..9b7f77d72e 100644 --- a/iphone/CoreApi/CoreApi/Storage/MWMMapNodeAttributes.h +++ b/iphone/CoreApi/CoreApi/Storage/MWMMapNodeAttributes.h @@ -10,7 +10,7 @@ typedef NS_ENUM(NSInteger, MWMMapNodeStatus) { MWMMapNodeStatusOnDisk, MWMMapNodeStatusNotDownloaded, MWMMapNodeStatusPartly -}; +} NS_SWIFT_NAME(MapNodeStatus); NS_ASSUME_NONNULL_BEGIN diff --git a/iphone/CoreApi/CoreApi/Storage/MWMStorage.h b/iphone/CoreApi/CoreApi/Storage/MWMStorage.h index 6f071a8101..5e58ec6f0f 100644 --- a/iphone/CoreApi/CoreApi/Storage/MWMStorage.h +++ b/iphone/CoreApi/CoreApi/Storage/MWMStorage.h @@ -14,35 +14,53 @@ extern NSInteger const kStorageCellularForbidden; extern NSInteger const kStorageRoutingActive; extern NSInteger const kStorageHaveUnsavedEdits; +NS_SWIFT_NAME(StorageObserver) +@protocol MWMStorageObserver + +- (void)processCountryEvent:(NSString *)countryId; + +@optional + +- (void)processCountry:(NSString *)countryId + downloadedBytes:(uint64_t)downloadedBytes + totalBytes:(uint64_t)totalBytes; + +@end + NS_SWIFT_NAME(Storage) @interface MWMStorage : NSObject -+ (BOOL)downloadNode:(NSString *)countryId error:(NSError * __autoreleasing _Nullable *)error; -+ (void)retryDownloadNode:(NSString *)countryId; -+ (BOOL)updateNode:(NSString *)countryId error:(NSError * __autoreleasing _Nullable *)error; -+ (BOOL)deleteNode:(NSString *)countryId ++ (instancetype)sharedStorage; + +- (BOOL)downloadNode:(NSString *)countryId error:(NSError * __autoreleasing _Nullable *)error; +- (void)retryDownloadNode:(NSString *)countryId; +- (BOOL)updateNode:(NSString *)countryId error:(NSError * __autoreleasing _Nullable *)error; +- (BOOL)deleteNode:(NSString *)countryId ignoreUnsavedEdits:(BOOL)force error:(NSError * __autoreleasing _Nullable *)error; -+ (void)cancelDownloadNode:(NSString *)countryId; -+ (void)showNode:(NSString *)countryId; -+ (BOOL)downloadNodes:(NSArray *)countryIds error:(NSError * __autoreleasing _Nullable *)error; +- (void)cancelDownloadNode:(NSString *)countryId; +- (void)showNode:(NSString *)countryId; +- (BOOL)downloadNodes:(NSArray *)countryIds error:(NSError * __autoreleasing _Nullable *)error; -+ (BOOL)haveDownloadedCountries; -+ (BOOL)downloadInProgress; -+ (void)enableCellularDownload:(BOOL)enable; +- (BOOL)haveDownloadedCountries; +- (BOOL)downloadInProgress; +- (void)enableCellularDownload:(BOOL)enable; + +- (void)addObserver:(id)observer; +- (void)removeObserver:(id)observer; #pragma mark - Attributes -+ (NSArray *)allCountries; -+ (NSArray *)allCountriesWithParent:(NSString *)countryId; -+ (NSArray *)availableCountriesWithParent:(NSString *)countryId; -+ (NSArray *)downloadedCountries; -+ (NSArray *)downloadedCountriesWithParent:(NSString *)countryId; -+ (MWMMapNodeAttributes *)attributesForCountry:(NSString *)countryId; -+ (MWMMapNodeAttributes *)attributesForRoot; -+ (NSString *)nameForCountry:(NSString *)countryId; -+ (nullable NSArray *)nearbyAvailableCountries:(CLLocationCoordinate2D)location; -+ (MWMMapUpdateInfo *)updateInfoWithParent:(nullable NSString *)countryId; +- (NSArray *)allCountries; +- (NSArray *)allCountriesWithParent:(NSString *)countryId; +- (NSArray *)availableCountriesWithParent:(NSString *)countryId; +- (NSArray *)downloadedCountries; +- (NSArray *)downloadedCountriesWithParent:(NSString *)countryId; +- (MWMMapNodeAttributes *)attributesForCountry:(NSString *)countryId; +- (MWMMapNodeAttributes *)attributesForRoot; +- (NSString *)nameForCountry:(NSString *)countryId; +- (nullable NSArray *)nearbyAvailableCountries:(CLLocationCoordinate2D)location; +- (MWMMapUpdateInfo *)updateInfoWithParent:(nullable NSString *)countryId; @end diff --git a/iphone/CoreApi/CoreApi/Storage/MWMStorage.mm b/iphone/CoreApi/CoreApi/Storage/MWMStorage.mm index 3217a681ae..2b9d993dd9 100644 --- a/iphone/CoreApi/CoreApi/Storage/MWMStorage.mm +++ b/iphone/CoreApi/CoreApi/Storage/MWMStorage.mm @@ -15,9 +15,60 @@ NSInteger const kStorageHaveUnsavedEdits = 5; using namespace storage; +@interface MWMStorage () + +@property(nonatomic, strong) NSHashTable> *observers; + +@end + @implementation MWMStorage -+ (BOOL)downloadNode:(NSString *)countryId error:(NSError *__autoreleasing _Nullable *)error { ++ (instancetype)sharedStorage { + static MWMStorage *instance; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + +- (instancetype)init { + self = [super init]; + if (self) { + _observers = [NSHashTable weakObjectsHashTable]; + NSHashTable *observers = _observers; + + auto const &countryFunction = [observers](CountryId const & countryId) { + NSHashTable *observersCopy = [observers copy]; + for (id observer in observersCopy) { + [observer processCountryEvent:@(countryId.c_str())]; + } + }; + + auto const &progressFunction = [observers](CountryId const & countryId, downloader::Progress const & progress) { + NSHashTable *observersCopy = [observers copy]; + for (id observer in observersCopy) { + if ([observer respondsToSelector:@selector(processCountry:downloadedBytes:totalBytes:)]) { + [observer processCountry:@(countryId.c_str()) downloadedBytes:progress.first totalBytes:progress.second]; + } + } + }; + + GetFramework().GetStorage().Subscribe(countryFunction, progressFunction); + } + return self; +} + +- (void)addObserver:(id)observer { + [self.observers addObject:observer]; +} + +- (void)removeObserver:(id)observer { + [self.observers removeObject:observer]; +} + + +- (BOOL)downloadNode:(NSString *)countryId error:(NSError *__autoreleasing _Nullable *)error { if (IsEnoughSpaceForDownload(countryId.UTF8String, GetFramework().GetStorage())) { NSError *connectionError; if ([self checkConnection:&connectionError]) { @@ -33,13 +84,13 @@ using namespace storage; return NO; } -+ (void)retryDownloadNode:(NSString *)countryId { +- (void)retryDownloadNode:(NSString *)countryId { if ([self checkConnection:nil]) { GetFramework().GetStorage().RetryDownloadNode(countryId.UTF8String); } } -+ (BOOL)updateNode:(NSString *)countryId error:(NSError *__autoreleasing _Nullable *)error { +- (BOOL)updateNode:(NSString *)countryId error:(NSError *__autoreleasing _Nullable *)error { if (IsEnoughSpaceForUpdate(countryId.UTF8String, GetFramework().GetStorage())) { NSError *connectionError; if ([self checkConnection:&connectionError]) { @@ -55,7 +106,7 @@ using namespace storage; return NO; } -+ (BOOL)deleteNode:(NSString *)countryId +- (BOOL)deleteNode:(NSString *)countryId ignoreUnsavedEdits:(BOOL)force error:(NSError *__autoreleasing _Nullable *)error { auto &f = GetFramework(); @@ -79,15 +130,15 @@ using namespace storage; return NO; } -+ (void)cancelDownloadNode:(NSString *)countryId { +- (void)cancelDownloadNode:(NSString *)countryId { GetFramework().GetStorage().CancelDownloadNode(countryId.UTF8String); } -+ (void)showNode:(NSString *)countryId { +- (void)showNode:(NSString *)countryId { GetFramework().ShowNode(countryId.UTF8String); } -+ (BOOL)downloadNodes:(NSArray *)countryIds error:(NSError *__autoreleasing _Nullable *)error { +- (BOOL)downloadNodes:(NSArray *)countryIds error:(NSError *__autoreleasing _Nullable *)error { auto &s = GetFramework().GetStorage(); MwmSize requiredSize = s.GetMaxMwmSizeBytes(); @@ -114,7 +165,7 @@ using namespace storage; return NO; } -+ (BOOL)checkConnection:(NSError *__autoreleasing *)error { +- (BOOL)checkConnection:(NSError *__autoreleasing *)error { switch (Platform::ConnectionStatus()) { case Platform::EConnectionType::CONNECTION_NONE: if (error) { @@ -145,26 +196,26 @@ using namespace storage; } } -+ (BOOL)haveDownloadedCountries { +- (BOOL)haveDownloadedCountries { return GetFramework().GetStorage().HaveDownloadedCountries(); } -+ (BOOL)downloadInProgress { +- (BOOL)downloadInProgress { return GetFramework().GetStorage().IsDownloadInProgress(); } -+ (void)enableCellularDownload:(BOOL)enable { +- (void)enableCellularDownload:(BOOL)enable { GetFramework().GetDownloadingPolicy().EnableCellularDownload(enable); } #pragma mark - Attributes -+ (NSArray *)allCountries { +- (NSArray *)allCountries { NSString *rootId = @(GetFramework().GetStorage().GetRootId().c_str()); return [self allCountriesWithParent:rootId]; } -+ (NSArray *)allCountriesWithParent:(NSString *)countryId { +- (NSArray *)allCountriesWithParent:(NSString *)countryId { storage::CountriesVec downloadedChildren; storage::CountriesVec availableChildren; GetFramework().GetStorage().GetChildrenInGroups(countryId.UTF8String, downloadedChildren, availableChildren, @@ -177,7 +228,7 @@ using namespace storage; return [result copy]; } -+ (NSArray *)availableCountriesWithParent:(NSString *)countryId { +- (NSArray *)availableCountriesWithParent:(NSString *)countryId { storage::CountriesVec downloadedChildren; storage::CountriesVec availableChildren; GetFramework().GetStorage().GetChildrenInGroups(countryId.UTF8String, downloadedChildren, availableChildren); @@ -189,12 +240,12 @@ using namespace storage; return [result copy]; } -+ (NSArray *)downloadedCountries { +- (NSArray *)downloadedCountries { NSString *rootId = @(GetFramework().GetStorage().GetRootId().c_str()); return [self downloadedCountriesWithParent:rootId]; } -+ (NSArray *)downloadedCountriesWithParent:(NSString *)countryId { +- (NSArray *)downloadedCountriesWithParent:(NSString *)countryId { storage::CountriesVec downloadedChildren; storage::CountriesVec availableChildren; GetFramework().GetStorage().GetChildrenInGroups(countryId.UTF8String, downloadedChildren, availableChildren); @@ -206,7 +257,7 @@ using namespace storage; return [result copy]; } -+ (MWMMapNodeAttributes *)attributesForCountry:(NSString *)countryId { +- (MWMMapNodeAttributes *)attributesForCountry:(NSString *)countryId { auto const &s = GetFramework().GetStorage(); storage::NodeAttrs nodeAttrs; s.GetNodeAttrs(countryId.UTF8String, nodeAttrs); @@ -219,15 +270,15 @@ using namespace storage; hasChildren:!children.empty()]; } -+ (MWMMapNodeAttributes *)attributesForRoot { +- (MWMMapNodeAttributes *)attributesForRoot { return [self attributesForCountry:@(GetFramework().GetStorage().GetRootId().c_str())]; } -+ (NSString *)nameForCountry:(NSString *)countryId { +- (NSString *)nameForCountry:(NSString *)countryId { return @(GetFramework().GetStorage().GetNodeLocalName(countryId.UTF8String).c_str()); } -+ (NSArray *)nearbyAvailableCountries:(CLLocationCoordinate2D)location { +- (NSArray *)nearbyAvailableCountries:(CLLocationCoordinate2D)location { auto &f = GetFramework(); storage::CountriesVec closestCoutryIds; f.GetCountryInfoGetter().GetRegionsCountryId(mercator::FromLatLon(location.latitude, location.longitude), @@ -243,7 +294,7 @@ using namespace storage; return nearmeCountries.count > 0 ? [nearmeCountries copy] : nil; } -+ (MWMMapUpdateInfo *)updateInfoWithParent:(nullable NSString *)countryId { +- (MWMMapUpdateInfo *)updateInfoWithParent:(nullable NSString *)countryId { auto const &s = GetFramework().GetStorage(); Storage::UpdateInfo updateInfo; if (countryId.length > 0) { diff --git a/iphone/Maps/Bridging-Header.h b/iphone/Maps/Bridging-Header.h index 907e462a40..ff02ae72ba 100644 --- a/iphone/Maps/Bridging-Header.h +++ b/iphone/Maps/Bridging-Header.h @@ -34,7 +34,6 @@ #import "MWMController.h" #import "MWMEditorHelper.h" #import "MWMFrameworkListener.h" -#import "MWMFrameworkStorageObserver.h" #import "MWMGeoTrackerCore.h" #import "MWMKeyboard.h" #import "MWMLocationManager.h" diff --git a/iphone/Maps/Classes/CustomAlert/DownloadTransitMapsAlert/MWMDownloadTransitMapAlert.mm b/iphone/Maps/Classes/CustomAlert/DownloadTransitMapsAlert/MWMDownloadTransitMapAlert.mm index 6ac9fd01be..a33607cead 100644 --- a/iphone/Maps/Classes/CustomAlert/DownloadTransitMapsAlert/MWMDownloadTransitMapAlert.mm +++ b/iphone/Maps/Classes/CustomAlert/DownloadTransitMapsAlert/MWMDownloadTransitMapAlert.mm @@ -2,8 +2,6 @@ #import "MWMCircularProgress.h" #import "MWMDownloaderDialogCell.h" #import "MWMDownloaderDialogHeader.h" -#import "MWMFrameworkListener.h" -#import "MWMFrameworkStorageObserver.h" #import "MWMStorage+UI.h" #import "Statistics.h" #import "SwiftBridge.h" @@ -24,7 +22,7 @@ CGFloat const kMinimumOffset = 20.; CGFloat const kAnimationDuration = .05; } // namespace -@interface MWMDownloadTransitMapAlert () +@interface MWMDownloadTransitMapAlert () @property(copy, nonatomic) MWMVoidBlock cancelBlock; @property(copy, nonatomic) MWMDownloadBlock downloadBlock; @@ -102,7 +100,7 @@ CGFloat const kAnimationDuration = .05; alert->m_countries = storage::CountriesVec(countries.begin(), countries.end()); [alert configure]; [alert updateCountriesList]; - [MWMFrameworkListener addObserver:alert]; + [[MWMStorage sharedStorage] addObserver:alert]; return alert; } @@ -141,11 +139,11 @@ CGFloat const kAnimationDuration = .05; - (void)progressButtonPressed:(nonnull MWMCircularProgress *)progress { for (auto const & countryId : m_countries) - [MWMStorage cancelDownloadNode:@(countryId.c_str())]; + [[MWMStorage sharedStorage] cancelDownloadNode:@(countryId.c_str())]; [self cancelButtonTap]; } -#pragma mark - MWMFrameworkStorageObserver +#pragma mark - MWMStorageObserver - (void)processCountryEvent:(NSString *)countryId { @@ -292,7 +290,7 @@ CGFloat const kAnimationDuration = .05; - (void)close:(MWMVoidBlock)completion { - [MWMFrameworkListener removeObserver:self]; + [[MWMStorage sharedStorage] removeObserver:self]; [super close:completion]; } diff --git a/iphone/Maps/Classes/CustomViews/CircularProgress/MWMCircularProgressView.m b/iphone/Maps/Classes/CustomViews/CircularProgress/MWMCircularProgressView.m index ca6c4b2a69..c10915ffb2 100644 --- a/iphone/Maps/Classes/CustomViews/CircularProgress/MWMCircularProgressView.m +++ b/iphone/Maps/Classes/CustomViews/CircularProgress/MWMCircularProgressView.m @@ -116,8 +116,14 @@ static CGFloat angleWithProgress(CGFloat progress) { return 2.0 * M_PI * progres self.backgroundLayer.lineWidth = self.progressLayer.lineWidth = kLineWidth; self.backgroundLayer.strokeColor = self.spinnerBackgroundColor.CGColor; self.progressLayer.strokeColor = self.progressLayerColor; - CGRect rect = CGRectInset(self.bounds, kLineWidth, kLineWidth); - self.backgroundLayer.path = [UIBezierPath bezierPathWithOvalInRect:rect].CGPath; + CGPoint center = CGPointMake(self.width / 2.0, self.height / 2.0); + CGFloat radius = MIN(center.x, center.y) - kLineWidth; + UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:center + radius:radius + startAngle:angleWithProgress(0.0) + endAngle:angleWithProgress(1.0) + clockwise:YES]; + self.backgroundLayer.path = path.CGPath; NSString * imageName = self.images[@(self.state)]; if (imageName) { diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index ceb55508d4..edf71d79e0 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -8,7 +8,6 @@ #import "MWMEditBookmarkController.h" #import "MWMEditorViewController.h" #import "MWMFrameworkListener.h" -#import "MWMFrameworkStorageObserver.h" #import "MWMFrameworkObservers.h" #import "MWMLocationHelpers.h" #import "MWMMapDownloadDialog.h" @@ -74,7 +73,7 @@ NSString * const kPP2BookmarkEditingSegue = @"PP2BookmarkEditing"; @end -@interface MapViewController () @@ -430,6 +429,7 @@ NSString * const kPP2BookmarkEditingSegue = @"PP2BookmarkEditing"; [[MWMBookmarksManager sharedManager] addObserver: self]; [[MWMBookmarksManager sharedManager] loadBookmarks]; [MWMFrameworkListener addObserver:self]; + [[MWMStorage sharedStorage] addObserver:self]; } - (void)dealloc { @@ -657,7 +657,7 @@ NSString * const kPP2BookmarkEditingSegue = @"PP2BookmarkEditing"; [self.downloadDialog processViewportCountryEvent:countryId]; } -#pragma mark - MWMFrameworkStorageObserver +#pragma mark - MWMStorageObserver - (void)processCountryEvent:(NSString *)countryId { diff --git a/iphone/Maps/Classes/MapsAppDelegate.mm b/iphone/Maps/Classes/MapsAppDelegate.mm index fb0400bcb3..74a597b640 100644 --- a/iphone/Maps/Classes/MapsAppDelegate.mm +++ b/iphone/Maps/Classes/MapsAppDelegate.mm @@ -108,7 +108,7 @@ void OverrideUserAgent() using namespace osm_auth_ios; -@interface MapsAppDelegate () @@ -188,7 +188,7 @@ using namespace osm_auth_ios; [HttpThreadImpl setDownloadIndicatorProtocol:self]; InitLocalizedStrings(); GetFramework().SetupMeasurementSystem(); - [MWMFrameworkListener addObserver:self]; + [[MWMStorage sharedStorage] addObserver:self]; [MapsAppDelegate customizeAppearance]; self.standbyCounter = 0; @@ -613,7 +613,7 @@ continueUserActivity:(NSUserActivity *)userActivity return updateInfo.m_numberOfMwmFilesToUpdate; } -#pragma mark - MWMFrameworkStorageObserver +#pragma mark - MWMStorageObserver - (void)processCountryEvent:(NSString *)countryId { diff --git a/iphone/Maps/Classes/Widgets/MWMMapDownloadDialog.mm b/iphone/Maps/Classes/Widgets/MWMMapDownloadDialog.mm index 6c8237ac33..dc62efd70a 100644 --- a/iphone/Maps/Classes/Widgets/MWMMapDownloadDialog.mm +++ b/iphone/Maps/Classes/Widgets/MWMMapDownloadDialog.mm @@ -3,8 +3,6 @@ #import "CLLocation+Mercator.h" #import "MWMBookmarksBannerViewController.h" #import "MWMCircularProgress.h" -#import "MWMFrameworkListener.h" -#import "MWMFrameworkStorageObserver.h" #import "MWMMegafonBannerViewController.h" #import "MWMStorage+UI.h" #import "MapViewController.h" @@ -56,7 +54,7 @@ promo::DownloaderPromo::Banner getPromoBanner(std::string const &mwmId) { using namespace storage; -@interface MWMMapDownloadDialog () +@interface MWMMapDownloadDialog () @property(strong, nonatomic) IBOutlet UILabel *parentNode; @property(strong, nonatomic) IBOutlet UILabel *node; @property(strong, nonatomic) IBOutlet UILabel *nodeSize; @@ -140,10 +138,10 @@ using namespace storage; kStatScenario: kStatDownload }]; m_autoDownloadCountryId = m_countryId; - [MWMStorage downloadNode:@(m_countryId.c_str()) - onSuccess:^{ - [self showInQueue]; - }]; + [[MWMStorage sharedStorage] downloadNode:@(m_countryId.c_str()) + onSuccess:^{ + [self showInQueue]; + }]; } else { m_autoDownloadCountryId = kInvalidCountryId; [self showDownloadRequest]; @@ -189,7 +187,7 @@ using namespace storage; return; MapViewController *controller = self.controller; [controller.view insertSubview:self aboveSubview:controller.controlsView]; - [MWMFrameworkListener addObserver:self]; + [[MWMStorage sharedStorage] addObserver:self]; } - (void)removeFromSuperview { @@ -197,7 +195,7 @@ using namespace storage; [[MWMCarPlayService shared] hideNoMapAlert]; } self.progress.state = MWMCircularProgressStateNormal; - [MWMFrameworkListener removeObserver:self]; + [[MWMStorage sharedStorage] removeObserver:self]; [super removeFromSuperview]; } @@ -220,11 +218,11 @@ using namespace storage; kStatScenario: kStatDownload }]; [self showInQueue]; - [MWMStorage retryDownloadNode:@(self->m_countryId.c_str())]; + [[MWMStorage sharedStorage] retryDownloadNode:@(self->m_countryId.c_str())]; }; auto const cancelBlock = ^{ [Statistics logEvent:kStatDownloaderDownloadCancel withParameters:@{kStatFrom: kStatMap}]; - [MWMStorage cancelDownloadNode:@(self->m_countryId.c_str())]; + [[MWMStorage sharedStorage] cancelDownloadNode:@(self->m_countryId.c_str())]; }; switch (errorCode) { case NodeErrorCode::NoError: @@ -361,7 +359,7 @@ using namespace storage; [self layoutIfNeeded]; } -#pragma mark - MWMFrameworkStorageObserver +#pragma mark - MWMStorageObserver - (void)processCountryEvent:(NSString *)countryId { if (m_countryId != countryId.UTF8String) @@ -391,12 +389,12 @@ using namespace storage; kStatScenario: kStatDownload }]; [self showInQueue]; - [MWMStorage retryDownloadNode:@(m_countryId.c_str())]; + [[MWMStorage sharedStorage] retryDownloadNode:@(m_countryId.c_str())]; } else { [Statistics logEvent:kStatDownloaderDownloadCancel withParameters:@{kStatFrom: kStatMap}]; if (m_autoDownloadCountryId == m_countryId) self.isAutoDownloadCancelled = YES; - [MWMStorage cancelDownloadNode:@(m_countryId.c_str())]; + [[MWMStorage sharedStorage] cancelDownloadNode:@(m_countryId.c_str())]; } } @@ -419,8 +417,8 @@ using namespace storage; kStatFrom: kStatMap, kStatScenario: kStatDownload }]; - [MWMStorage downloadNode:@(m_countryId.c_str()) - onSuccess:^{ [self showInQueue]; }]; + [[MWMStorage sharedStorage] downloadNode:@(m_countryId.c_str()) + onSuccess:^{ [self showInQueue]; }]; } #pragma mark - Properties diff --git a/iphone/Maps/Core/Framework/MWMFrameworkListener.mm b/iphone/Maps/Core/Framework/MWMFrameworkListener.mm index 53bc5ba340..587dde7333 100644 --- a/iphone/Maps/Core/Framework/MWMFrameworkListener.mm +++ b/iphone/Maps/Core/Framework/MWMFrameworkListener.mm @@ -9,13 +9,11 @@ namespace { using Observer = id; using TRouteBuildingObserver = id; -using TStorageObserver = id; using TDrapeObserver = id; using Observers = NSHashTable; Protocol * pRouteBuildingObserver = @protocol(MWMFrameworkRouteBuilderObserver); -Protocol * pStorageObserver = @protocol(MWMFrameworkStorageObserver); Protocol * pDrapeObserver = @protocol(MWMFrameworkDrapeObserver); using TLoopBlock = void (^)(__kindof Observer observer); @@ -35,7 +33,6 @@ void loopWrappers(Observers * observers, TLoopBlock block) @interface MWMFrameworkListener () @property(nonatomic) Observers * routeBuildingObservers; -@property(nonatomic) Observers * storageObservers; @property(nonatomic) Observers * drapeObservers; @end @@ -58,8 +55,6 @@ void loopWrappers(Observers * observers, TLoopBlock block) MWMFrameworkListener * listener = [MWMFrameworkListener listener]; if ([observer conformsToProtocol:pRouteBuildingObserver]) [listener.routeBuildingObservers addObject:observer]; - if ([observer conformsToProtocol:pStorageObserver]) - [listener.storageObservers addObject:observer]; if ([observer conformsToProtocol:pDrapeObserver]) [listener.drapeObservers addObject:observer]; }); @@ -70,7 +65,6 @@ void loopWrappers(Observers * observers, TLoopBlock block) dispatch_async(dispatch_get_main_queue(), ^{ MWMFrameworkListener * listener = [MWMFrameworkListener listener]; [listener.routeBuildingObservers removeObject:observer]; - [listener.storageObservers removeObject:observer]; [listener.drapeObservers removeObject:observer]; }); } @@ -81,11 +75,9 @@ void loopWrappers(Observers * observers, TLoopBlock block) if (self) { _routeBuildingObservers = [Observers weakObjectsHashTable]; - _storageObservers = [Observers weakObjectsHashTable]; _drapeObservers = [Observers weakObjectsHashTable]; [self registerRouteBuilderListener]; - [self registerStorageObserver]; [self registerDrapeObserver]; } return self; @@ -138,26 +130,6 @@ void loopWrappers(Observers * observers, TLoopBlock block) }); } -#pragma mark - MWMFrameworkStorageObserver - -- (void)registerStorageObserver -{ - Observers * observers = self.storageObservers; - auto & s = GetFramework().GetStorage(); - s.Subscribe( - [observers](CountryId const & countryId) { - for (TStorageObserver observer in observers) - [observer processCountryEvent:@(countryId.c_str())]; - }, - [observers](CountryId const & countryId, downloader::Progress const & progress) { - for (TStorageObserver observer in observers) - { - if ([observer respondsToSelector:@selector(processCountry:downloadedBytes:totalBytes:)]) - [observer processCountry:@(countryId.c_str()) downloadedBytes:progress.first totalBytes:progress.second]; - } - }); -} - #pragma mark - MWMFrameworkDrapeObserver - (void)registerDrapeObserver diff --git a/iphone/Maps/Core/Framework/MWMFrameworkObservers.h b/iphone/Maps/Core/Framework/MWMFrameworkObservers.h index c0f1d1998e..de9b07e573 100644 --- a/iphone/Maps/Core/Framework/MWMFrameworkObservers.h +++ b/iphone/Maps/Core/Framework/MWMFrameworkObservers.h @@ -1,5 +1,4 @@ #import "MWMFrameworkObserver.h" -#import "MWMFrameworkStorageObserver.h" #import "MWMRouterRecommendation.h" #include "routing/router.hpp" diff --git a/iphone/Maps/Core/Framework/MWMFrameworkStorageObserver.h b/iphone/Maps/Core/Framework/MWMFrameworkStorageObserver.h deleted file mode 100644 index 6ead532cd8..0000000000 --- a/iphone/Maps/Core/Framework/MWMFrameworkStorageObserver.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "MWMFrameworkObserver.h" - -NS_ASSUME_NONNULL_BEGIN - -@protocol MWMFrameworkStorageObserver - -- (void)processCountryEvent:(NSString *)countryId; - -@optional - -- (void)processCountry:(NSString *)countryId - downloadedBytes:(uint64_t)downloadedBytes - totalBytes:(uint64_t)totalBytes; - -@end - -NS_ASSUME_NONNULL_END diff --git a/iphone/Maps/Core/Routing/MWMRouter.mm b/iphone/Maps/Core/Routing/MWMRouter.mm index d633b6f9b0..667dbb67f7 100644 --- a/iphone/Maps/Core/Routing/MWMRouter.mm +++ b/iphone/Maps/Core/Routing/MWMRouter.mm @@ -726,8 +726,7 @@ void logPointEvent(MWMRoutePoint * point, NSString * eventType) for (auto const &cid : downloadCountries) { [array addObject:@(cid.c_str())]; } - [MWMStorage downloadNodes:array - onSuccess:onSuccess]; + [[MWMStorage sharedStorage] downloadNodes:array onSuccess:onSuccess]; } downloadCompleteBlock:^{ [MWMRouter rebuildWithBestRouter:NO]; diff --git a/iphone/Maps/Core/Storage/MWMStorage+UI.h b/iphone/Maps/Core/Storage/MWMStorage+UI.h index 93db970d89..903baff3d8 100644 --- a/iphone/Maps/Core/Storage/MWMStorage+UI.h +++ b/iphone/Maps/Core/Storage/MWMStorage+UI.h @@ -4,12 +4,12 @@ NS_ASSUME_NONNULL_BEGIN @interface MWMStorage (UI) -+ (void)downloadNode:(NSString *)countryId; -+ (void)downloadNode:(NSString *)countryId onSuccess:(nullable MWMVoidBlock)success; -+ (void)updateNode:(NSString *)countryId; -+ (void)updateNode:(NSString *)countryId onCancel:(nullable MWMVoidBlock)cancel; -+ (void)deleteNode:(NSString *)countryId; -+ (void)downloadNodes:(NSArray *)countryIds onSuccess:(nullable MWMVoidBlock)success; +- (void)downloadNode:(NSString *)countryId; +- (void)downloadNode:(NSString *)countryId onSuccess:(nullable MWMVoidBlock)success; +- (void)updateNode:(NSString *)countryId; +- (void)updateNode:(NSString *)countryId onCancel:(nullable MWMVoidBlock)cancel; +- (void)deleteNode:(NSString *)countryId; +- (void)downloadNodes:(NSArray *)countryIds onSuccess:(nullable MWMVoidBlock)success; @end diff --git a/iphone/Maps/Core/Storage/MWMStorage+UI.m b/iphone/Maps/Core/Storage/MWMStorage+UI.m index 30a960a828..1d474c350c 100644 --- a/iphone/Maps/Core/Storage/MWMStorage+UI.m +++ b/iphone/Maps/Core/Storage/MWMStorage+UI.m @@ -3,9 +3,9 @@ @implementation MWMStorage (UI) -+ (void)handleError:(NSError *)error { +- (void)handleError:(NSError *)error { if (error.code == kStorageNotEnoughSpace) { - [[MWMAlertViewController activeAlertController] presentNotEnoughSpaceAlert]; + [[MWMAlertViewController activeAlertController] presentNotEnoughSpaceAlert]; } else if (error.code == kStorageNoConnection) { [[MWMAlertViewController activeAlertController] presentNoConnectionAlert]; } else if (error.code == kStorageRoutingActive) { @@ -15,18 +15,18 @@ } } -+ (void)downloadNode:(NSString *)countryId { +- (void)downloadNode:(NSString *)countryId { [self downloadNode:countryId onSuccess:nil]; } -+ (void)downloadNode:(NSString *)countryId onSuccess:(MWMVoidBlock)success { +- (void)downloadNode:(NSString *)countryId onSuccess:(MWMVoidBlock)success { NSError *error; [self downloadNode:countryId error:&error]; if (error) { if (error.code == kStorageCellularForbidden) { __weak __typeof(self) ws = self; [[MWMAlertViewController activeAlertController] presentNoWiFiAlertWithOkBlock:^{ - [MWMStorage enableCellularDownload:YES]; + [self enableCellularDownload:YES]; [ws downloadNode:countryId]; } andCancelBlock:nil]; } else { @@ -39,18 +39,18 @@ } } -+ (void)updateNode:(NSString *)countryId { +- (void)updateNode:(NSString *)countryId { [self updateNode:countryId onCancel:nil]; } -+ (void)updateNode:(NSString *)countryId onCancel:(MWMVoidBlock)cancel { +- (void)updateNode:(NSString *)countryId onCancel:(MWMVoidBlock)cancel { NSError *error; [self updateNode:countryId error:&error]; if (error) { if (error.code == kStorageCellularForbidden) { __weak __typeof(self) ws = self; [[MWMAlertViewController activeAlertController] presentNoWiFiAlertWithOkBlock:^{ - [MWMStorage enableCellularDownload:YES]; + [self enableCellularDownload:YES]; [ws updateNode:countryId onCancel:cancel]; } andCancelBlock:cancel]; } else { @@ -62,18 +62,18 @@ } } -+ (void)deleteNode:(NSString *)countryId { +- (void)deleteNode:(NSString *)countryId { [self deleteNode:countryId ignoreUnsavedEdits:NO]; } -+ (void)deleteNode:(NSString *)countryId ignoreUnsavedEdits:(BOOL)force { +- (void)deleteNode:(NSString *)countryId ignoreUnsavedEdits:(BOOL)force { NSError *error; [self deleteNode:countryId ignoreUnsavedEdits:force error:&error]; if (error) { __weak __typeof(self) ws = self; if (error.code == kStorageCellularForbidden) { [[MWMAlertViewController activeAlertController] presentNoWiFiAlertWithOkBlock:^{ - [MWMStorage enableCellularDownload:YES]; + [self enableCellularDownload:YES]; [ws deleteNode:countryId]; } andCancelBlock:nil]; } else if (error.code == kStorageHaveUnsavedEdits) { @@ -86,14 +86,14 @@ } } -+ (void)downloadNodes:(NSArray *)countryIds onSuccess:(nullable MWMVoidBlock)success { +- (void)downloadNodes:(NSArray *)countryIds onSuccess:(nullable MWMVoidBlock)success { NSError *error; [self downloadNodes:countryIds error:&error]; if (error) { if (error.code == kStorageCellularForbidden) { __weak __typeof(self) ws = self; [[MWMAlertViewController activeAlertController] presentNoWiFiAlertWithOkBlock:^{ - [MWMStorage enableCellularDownload:YES]; + [self enableCellularDownload:YES]; [ws downloadNodes:countryIds onSuccess:success]; } andCancelBlock:nil]; } else { diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index aa28f397bb..6f039f9b9e 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -1430,7 +1430,6 @@ 473464A6218B0BC000D6AF5B /* MWMPurchaseValidation.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMPurchaseValidation.mm; sourceTree = ""; }; 4735008923A83CF700661A95 /* DownloadedMapsDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadedMapsDataSource.swift; sourceTree = ""; }; 473500C023A8F81800661A95 /* MWMFrameworkObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMFrameworkObserver.h; sourceTree = ""; }; - 473500C123A8F85A00661A95 /* MWMFrameworkStorageObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMFrameworkStorageObserver.h; sourceTree = ""; }; 4738A8E6239FC513007C0F43 /* AdBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdBannerView.swift; sourceTree = ""; }; 4738A8E8239FC526007C0F43 /* AdBannerView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AdBannerView.xib; sourceTree = ""; }; 473CBF9A2164DD470059BD54 /* SettingsTableViewSelectableProgressCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTableViewSelectableProgressCell.swift; sourceTree = ""; }; @@ -2960,7 +2959,6 @@ 3486B5131E27AD3B0069C126 /* MWMFrameworkListener.mm */, 3486B5141E27AD3B0069C126 /* MWMFrameworkObservers.h */, 473500C023A8F81800661A95 /* MWMFrameworkObserver.h */, - 473500C123A8F85A00661A95 /* MWMFrameworkStorageObserver.h */, ); path = Framework; sourceTree = ""; diff --git a/iphone/Maps/UI/Autoupdate/MWMAutoupdateController.mm b/iphone/Maps/UI/Autoupdate/MWMAutoupdateController.mm index fa1104a041..86c37f8e2e 100644 --- a/iphone/Maps/UI/Autoupdate/MWMAutoupdateController.mm +++ b/iphone/Maps/UI/Autoupdate/MWMAutoupdateController.mm @@ -1,7 +1,5 @@ #import "MWMAutoupdateController.h" #import "MWMCircularProgress.h" -#import "MWMFrameworkListener.h" -#import "MWMFrameworkStorageObserver.h" #import "MWMStorage+UI.h" #import "Statistics.h" #import "SwiftBridge.h" @@ -143,7 +141,7 @@ using namespace storage; @end -@interface MWMAutoupdateController () +@interface MWMAutoupdateController () { std::unordered_set m_updatingCountries; } @@ -164,7 +162,7 @@ using namespace storage; controller.todo = todo; auto view = static_cast(controller.view); view.delegate = controller; - [MWMFrameworkListener addObserver:controller]; + [[MWMStorage sharedStorage] addObserver:controller]; [controller updateSize]; return controller; } @@ -179,7 +177,7 @@ using namespace storage; if (self.todo == Framework::DoAfterUpdate::AutoupdateMaps) { [view stateDownloading]; - [MWMStorage updateNode:RootId() onCancel:^{ + [[MWMStorage sharedStorage] updateNode:RootId() onCancel:^{ [self updateSize]; [view stateWaiting]; }]; @@ -196,7 +194,7 @@ using namespace storage; { [static_cast(self.view) stopSpinner]; [self dismissViewControllerAnimated:YES completion:^{ - [MWMFrameworkListener removeObserver:self]; + [[MWMStorage sharedStorage] removeObserver:self]; }]; } @@ -216,7 +214,7 @@ using namespace storage; { MWMAutoupdateView *view = (MWMAutoupdateView *)self.view; [view stateDownloading]; - [MWMStorage updateNode:RootId() onCancel:^{ + [[MWMStorage sharedStorage] updateNode:RootId() onCancel:^{ [self updateSize]; [view stateWaiting]; }]; @@ -238,7 +236,7 @@ using namespace storage; [UIAlertAction actionWithTitle:L(@"cancel_download") style:UIAlertActionStyleDestructive handler:^(UIAlertAction * action) { - [MWMStorage cancelDownloadNode:RootId()]; + [[MWMStorage sharedStorage] cancelDownloadNode:RootId()]; [self dismiss]; [Statistics logEvent:view.state == State::Downloading ? kStatDownloaderOnStartScreenCancelDownload @@ -279,7 +277,7 @@ using namespace storage; - (void)progressButtonPressed:(MWMCircularProgress *)progress { [self cancel]; } -#pragma mark - MWMFrameworkStorageObserver +#pragma mark - MWMStorageObserver - (void)processCountryEvent:(NSString *)countryId { @@ -313,7 +311,7 @@ using namespace storage; { [self updateSize]; [static_cast(self.view) stateWaiting]; - [MWMStorage cancelDownloadNode:RootId()]; + [[MWMStorage sharedStorage] cancelDownloadNode:RootId()]; auto errorType = ^NSString * (NodeErrorCode code) { switch (code) diff --git a/iphone/Maps/UI/Downloader/AvailableMapsDataSource.swift b/iphone/Maps/UI/Downloader/AvailableMapsDataSource.swift index 2e6787c5cf..adcd610a7c 100644 --- a/iphone/Maps/UI/Downloader/AvailableMapsDataSource.swift +++ b/iphone/Maps/UI/Downloader/AvailableMapsDataSource.swift @@ -18,16 +18,16 @@ class AvailableMapsDataSource { self.parentCountryId = parentCountryId let countryIds: [String] if let parentCountryId = parentCountryId { - countryIds = Storage.allCountries(withParent: parentCountryId) + countryIds = Storage.shared().allCountries(withParent: parentCountryId) } else { - countryIds = Storage.allCountries() + countryIds = Storage.shared().allCountries() } configSections(countryIds, location: location) } private func configSections(_ countryIds: [String], location: CLLocationCoordinate2D?) { let countries = countryIds.map { - CountryIdAndName(countryId: $0, name: Storage.name(forCountry: $0)) + CountryIdAndName(countryId: $0, name: Storage.shared().name(forCountry: $0)) }.sorted { $0.countryName.compare($1.countryName) == .orderedAscending } @@ -35,7 +35,7 @@ class AvailableMapsDataSource { sections = [] sectionsContent = [:] - if let location = location, let nearbySection = Storage.nearbyAvailableCountries(location) { + if let location = location, let nearbySection = Storage.shared().nearbyAvailableCountries(location) { sections?.append(Const.locationArrow) sectionsContent![Const.locationArrow] = nearbySection } @@ -63,7 +63,7 @@ extension AvailableMapsDataSource: IDownloaderDataSource { guard let parentCountryId = parentCountryId else { return L("download_maps") } - return Storage.name(forCountry: parentCountryId) + return Storage.shared().name(forCountry: parentCountryId) } var isRoot: Bool { @@ -76,9 +76,9 @@ extension AvailableMapsDataSource: IDownloaderDataSource { func parentAttributes() -> MapNodeAttributes { guard let parentId = parentCountryId else { - return Storage.attributesForRoot() + return Storage.shared().attributesForRoot() } - return Storage.attributes(forCountry: parentId) + return Storage.shared().attributes(forCountry: parentId) } func numberOfSections() -> Int { @@ -100,7 +100,7 @@ extension AvailableMapsDataSource: IDownloaderDataSource { let sectionIndex = sections![indexPath.section] let sectionItems = sectionsContent![sectionIndex] let countryId = sectionItems![indexPath.item] - return Storage.attributes(forCountry: countryId) + return Storage.shared().attributes(forCountry: countryId) } func matchedName(at indexPath: IndexPath) -> String? { diff --git a/iphone/Maps/UI/Downloader/DownloadMapsViewController.swift b/iphone/Maps/UI/Downloader/DownloadMapsViewController.swift index 9dba832292..1042adb823 100644 --- a/iphone/Maps/UI/Downloader/DownloadMapsViewController.swift +++ b/iphone/Maps/UI/Downloader/DownloadMapsViewController.swift @@ -70,8 +70,8 @@ class DownloadMapsViewController: MWMViewController { let addMapsButton = button(with: UIImage(named: "ic_nav_bar_add"), action: #selector(onAddMaps)) navigationItem.rightBarButtonItem = addMapsButton } - MWMFrameworkListener.add(self) - noMapsContainer.isHidden = !dataSource.isEmpty || Storage.downloadInProgress() + Storage.shared().add(self) + noMapsContainer.isHidden = !dataSource.isEmpty || Storage.shared().downloadInProgress() if !dataSource.isRoot { searchBarTopOffset.constant = -searchBar.frame.height } else { @@ -124,7 +124,7 @@ class DownloadMapsViewController: MWMViewController { switch $0 { case .showOnMap: action = UIAlertAction(title: L("zoom_to_country"), style: .default, handler: { _ in - Storage.showNode(nodeAttrs.countryId) + Storage.shared().showNode(nodeAttrs.countryId) self.navigationController?.popToRootViewController(animated: true) }) case .download: @@ -132,26 +132,26 @@ class DownloadMapsViewController: MWMViewController { action = UIAlertAction(title: "\(prefix) (\(formattedSize(nodeAttrs.totalSize)))", style: .default, handler: { _ in - Storage.downloadNode(nodeAttrs.countryId) + Storage.shared().downloadNode(nodeAttrs.countryId) }) case .update: let size = formattedSize(nodeAttrs.totalUpdateSizeBytes) let title = "\(L("downloader_status_outdated")) \(size)" action = UIAlertAction(title: title, style: .default, handler: { _ in - Storage.updateNode(nodeAttrs.countryId) + Storage.shared().updateNode(nodeAttrs.countryId) }) case .cancelDownload: action = UIAlertAction(title: L("cancel_download"), style: .destructive, handler: { _ in - Storage.cancelDownloadNode(nodeAttrs.countryId) + Storage.shared().cancelDownloadNode(nodeAttrs.countryId) Statistics.logEvent(kStatDownloaderDownloadCancel, withParameters: [kStatFrom: kStatMap]) }) case .retryDownload: action = UIAlertAction(title: L("downloader_retry"), style: .destructive, handler: { _ in - Storage.retryDownloadNode(nodeAttrs.countryId) + Storage.shared().retryDownloadNode(nodeAttrs.countryId) }) case .delete: action = UIAlertAction(title: L("downloader_delete_map"), style: .destructive, handler: { _ in - Storage.deleteNode(nodeAttrs.countryId) + Storage.shared().deleteNode(nodeAttrs.countryId) }) } actionSheet.addAction(action) @@ -189,7 +189,7 @@ class DownloadMapsViewController: MWMViewController { } } } else { - let updateInfo = Storage.updateInfo(withParent: dataSource.parentAttributes().countryId) + let updateInfo = Storage.shared().updateInfo(withParent: dataSource.parentAttributes().countryId) if updateInfo.numberOfFiles > 0 { setAllMapsButton(.download("\(L("downloader_update_all_button")) (\(formattedSize(updateInfo.updateSize)))")) } else { @@ -204,9 +204,9 @@ class DownloadMapsViewController: MWMViewController { @IBAction func onAllMaps(_ sender: UIButton) { skipCountryEvent = true if mode == .downloaded { - Storage.updateNode(dataSource.parentAttributes().countryId) + Storage.shared().updateNode(dataSource.parentAttributes().countryId) } else { - Storage.downloadNode(dataSource.parentAttributes().countryId) + Storage.shared().downloadNode(dataSource.parentAttributes().countryId) } skipCountryEvent = false self.processCountryEvent(dataSource.parentAttributes().countryId) @@ -214,7 +214,7 @@ class DownloadMapsViewController: MWMViewController { @IBAction func onCancelAllMaps(_ sender: UIButton) { skipCountryEvent = true - Storage.cancelDownloadNode(dataSource.parentAttributes().countryId) + Storage.shared().cancelDownloadNode(dataSource.parentAttributes().countryId) Statistics.logEvent(kStatDownloaderDownloadCancel, withParameters: [kStatFrom: kStatMap]) skipCountryEvent = false self.processCountryEvent(dataSource.parentAttributes().countryId) @@ -298,7 +298,7 @@ extension DownloadMapsViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { if editingStyle == .delete{ let nodeAttrs = dataSource.item(at: indexPath) - Storage.deleteNode(nodeAttrs.countryId) + Storage.shared().deleteNode(nodeAttrs.countryId) } } } @@ -349,14 +349,14 @@ extension DownloadMapsViewController: MWMMapDownloaderTableViewCellDelegate { let nodeAttrs = dataSource.item(at: indexPath) switch (nodeAttrs.nodeStatus) { case .undefined, .error: - Storage.retryDownloadNode(nodeAttrs.countryId) + Storage.shared().retryDownloadNode(nodeAttrs.countryId) break case .downloading, .applying, .inQueue: - Storage.cancelDownloadNode(nodeAttrs.countryId) + Storage.shared().cancelDownloadNode(nodeAttrs.countryId) Statistics.logEvent(kStatDownloaderDownloadCancel, withParameters: [kStatFrom: kStatMap]) break case .onDiskOutOfDate: - Storage.updateNode(nodeAttrs.countryId) + Storage.shared().updateNode(nodeAttrs.countryId) break case .onDisk: //do nothing @@ -365,7 +365,7 @@ extension DownloadMapsViewController: MWMMapDownloaderTableViewCellDelegate { if nodeAttrs.hasChildren { showChildren(nodeAttrs) } else { - Storage.downloadNode(nodeAttrs.countryId) + Storage.shared().downloadNode(nodeAttrs.countryId) } break @unknown default: @@ -380,17 +380,16 @@ extension DownloadMapsViewController: MWMMapDownloaderTableViewCellDelegate { } } -// MARK: - MWMFrameworkStorageObserver +// MARK: - StorageObserver -extension DownloadMapsViewController: MWMFrameworkStorageObserver { +extension DownloadMapsViewController: StorageObserver { func processCountryEvent(_ countryId: String) { - print("processCountryEvent: \(countryId)") if skipCountryEvent && countryId == dataSource.parentAttributes().countryId { return } dataSource.reload { tableView.reloadData() - noMapsContainer.isHidden = !dataSource.isEmpty || Storage.downloadInProgress() + noMapsContainer.isHidden = !dataSource.isEmpty || Storage.shared().downloadInProgress() } if countryId == dataSource.parentAttributes().countryId { configButtons() diff --git a/iphone/Maps/UI/Downloader/DownloadedMapsDataSource.swift b/iphone/Maps/UI/Downloader/DownloadedMapsDataSource.swift index 1ea2f57e5c..e8593f9c6e 100644 --- a/iphone/Maps/UI/Downloader/DownloadedMapsDataSource.swift +++ b/iphone/Maps/UI/Downloader/DownloadedMapsDataSource.swift @@ -15,13 +15,13 @@ class DownloadedMapsDataSource { private class func loadData(_ parentId: String?) -> [String] { let countryIds: [String] if let parentId = parentId { - countryIds = Storage.downloadedCountries(withParent: parentId) + countryIds = Storage.shared().downloadedCountries(withParent: parentId) } else { - countryIds = Storage.downloadedCountries() + countryIds = Storage.shared().downloadedCountries() } return countryIds.map { - CountryIdAndName(countryId: $0, name: Storage.name(forCountry: $0)) + CountryIdAndName(countryId: $0, name: Storage.shared().name(forCountry: $0)) }.sorted { $0.countryName.compare($1.countryName) == .orderedAscending }.map { @@ -43,7 +43,7 @@ extension DownloadedMapsDataSource: IDownloaderDataSource { guard let parentCountryId = parentCountryId else { return L("downloader_my_maps_title") } - return Storage.name(forCountry: parentCountryId) + return Storage.shared().name(forCountry: parentCountryId) } var isRoot: Bool { @@ -56,9 +56,9 @@ extension DownloadedMapsDataSource: IDownloaderDataSource { func parentAttributes() -> MapNodeAttributes { guard let parentId = parentCountryId else { - return Storage.attributesForRoot() + return Storage.shared().attributesForRoot() } - return Storage.attributes(forCountry: parentId) + return Storage.shared().attributes(forCountry: parentId) } func numberOfSections() -> Int { @@ -75,7 +75,7 @@ extension DownloadedMapsDataSource: IDownloaderDataSource { } guard indexPath.section == 0 else { fatalError() } let countryId = countryIds[indexPath.item] - return Storage.attributes(forCountry: countryId) + return Storage.shared().attributes(forCountry: countryId) } func matchedName(at indexPath: IndexPath) -> String? { @@ -87,10 +87,10 @@ extension DownloadedMapsDataSource: IDownloaderDataSource { return searchDataSource.title(for: section) } if let parentCountryId = parentCountryId { - let attributes = Storage.attributes(forCountry: parentCountryId) - return Storage.name(forCountry: parentCountryId) + " (\(formattedSize(attributes.downloadedSize)))" + let attributes = Storage.shared().attributes(forCountry: parentCountryId) + return Storage.shared().name(forCountry: parentCountryId) + " (\(formattedSize(attributes.downloadedSize)))" } - let attributes = Storage.attributesForRoot() + let attributes = Storage.shared().attributesForRoot() return L("downloader_downloaded_subtitle") + " (\(formattedSize(attributes.downloadedSize)))" } diff --git a/iphone/Maps/UI/Downloader/SearchMapsDataSource.swift b/iphone/Maps/UI/Downloader/SearchMapsDataSource.swift index 961277ecc8..79be4b0b7f 100644 --- a/iphone/Maps/UI/Downloader/SearchMapsDataSource.swift +++ b/iphone/Maps/UI/Downloader/SearchMapsDataSource.swift @@ -25,7 +25,7 @@ extension SearchMapsDataSource: IDownloaderDataSource { } func parentAttributes() -> MapNodeAttributes { - return Storage.attributesForRoot() + return Storage.shared().attributesForRoot() } func numberOfItems(in section: Int) -> Int { @@ -33,7 +33,7 @@ extension SearchMapsDataSource: IDownloaderDataSource { } func item(at indexPath: IndexPath) -> MapNodeAttributes { - Storage.attributes(forCountry: searchResults[indexPath.item].countryId) + Storage.shared().attributes(forCountry: searchResults[indexPath.item].countryId) } func matchedName(at indexPath: IndexPath) -> String? { diff --git a/iphone/Maps/UI/PlacePage/Components/ActionBarViewController.swift b/iphone/Maps/UI/PlacePage/Components/ActionBarViewController.swift index 6cf272d79e..2ada8d5c9e 100644 --- a/iphone/Maps/UI/PlacePage/Components/ActionBarViewController.swift +++ b/iphone/Maps/UI/PlacePage/Components/ActionBarViewController.swift @@ -4,7 +4,8 @@ protocol ActionBarViewControllerDelegate: AnyObject { class ActionBarViewController: UIViewController { @IBOutlet var stackView: UIStackView! - + var downloadButton: ActionBarButton? = nil + var placePageData: PlacePageData! var isRoutePlanning = false var canAddStop = false @@ -14,9 +15,7 @@ class ActionBarViewController: UIViewController { weak var delegate: ActionBarViewControllerDelegate? - override func viewDidLoad() { - super.viewDidLoad() - + private func configureButtons() { if placePageData.isRoutePoint { visibleButtons.append(.routeRemoveStop) } else if placePageData.roadType != .none { @@ -46,16 +45,64 @@ class ActionBarViewController: UIViewController { disabled = !bookmarkData.isEditable } } - guard let button = ActionBarButton(delegate: self, - buttonType: buttonType, - partnerIndex: placePageData.partnerIndex, - isSelected: selected, - isDisabled: disabled) else { continue } + let button = ActionBarButton(delegate: self, + buttonType: buttonType, + partnerIndex: placePageData.partnerIndex, + isSelected: selected, + isDisabled: disabled) stackView.addArrangedSubview(button) + if buttonType == .download { + downloadButton = button + updateDownloadButtonState(placePageData.mapNodeAttributes.nodeStatus) + } + } + } + + func resetButtons() { + stackView.arrangedSubviews.forEach { + stackView.removeArrangedSubview($0) + $0.removeFromSuperview() + } + visibleButtons.removeAll() + additionalButtons.removeAll() + downloadButton = nil + configureButtons() + } + + override func viewDidLoad() { + super.viewDidLoad() + + configureButtons() + } + + func updateDownloadButtonState(_ nodeStatus: MapNodeStatus) { + guard let downloadButton = downloadButton else { return } + switch self.placePageData.mapNodeAttributes.nodeStatus { + case .downloading: + downloadButton.mapDownloadProgress?.state = .progress + case .applying, .inQueue: + downloadButton.mapDownloadProgress?.state = .spinner + case .error: + downloadButton.mapDownloadProgress?.state = .failed + case .onDisk, .undefined, .onDiskOutOfDate: + downloadButton.mapDownloadProgress?.state = .completed + case .notDownloaded, .partly: + downloadButton.mapDownloadProgress?.state = .normal + @unknown default: + fatalError() } } private func configButton1() { + switch placePageData.mapNodeAttributes.nodeStatus { + case .onDiskOutOfDate, .onDisk, .undefined: + break + case .downloading, .applying, .inQueue, .error, .notDownloaded, .partly: + visibleButtons.append(.download) + return + @unknown default: + fatalError() + } var buttons: [ActionBarButtonType] = [] if isRoutePlanning { buttons.append(.routeFrom) diff --git a/iphone/Maps/UI/PlacePage/Components/PlacePageButtonsViewController.swift b/iphone/Maps/UI/PlacePage/Components/PlacePageButtonsViewController.swift index 0fc5f60d62..ffc1a83187 100644 --- a/iphone/Maps/UI/PlacePage/Components/PlacePageButtonsViewController.swift +++ b/iphone/Maps/UI/PlacePage/Components/PlacePageButtonsViewController.swift @@ -11,7 +11,19 @@ class PlacePageButtonsViewController: UIViewController { @IBOutlet var editPlaceButton: UIButton! @IBOutlet var addBusinessButton: UIButton! + private var buttons: [UIButton?] { + [bookingButton, addPlaceButton, editPlaceButton, addBusinessButton] + } + var buttonsData: PlacePageButtonsData! + var buttonsEnabled = true { + didSet { + buttons.forEach { + $0?.isEnabled = buttonsEnabled + } + } + } + weak var delegate: PlacePageButtonsViewControllerDelegate? override func viewDidLoad() { @@ -22,7 +34,9 @@ class PlacePageButtonsViewController: UIViewController { editPlaceButton.isHidden = !buttonsData.showEditPlace addBusinessButton.isHidden = !buttonsData.showAddBusiness - // Do any additional setup after loading the view. + buttons.forEach { + $0?.isEnabled = buttonsEnabled + } } @IBAction func onBooking(_ sender: UIButton) { diff --git a/iphone/Maps/UI/PlacePage/PlacePageInteractor.swift b/iphone/Maps/UI/PlacePage/PlacePageInteractor.swift index 63dac99b90..52628db107 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageInteractor.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageInteractor.swift @@ -205,7 +205,16 @@ extension PlacePageInteractor: ActionBarViewControllerDelegate { case .call: MWMPlacePageManagerHelper.call(placePageData) case .download: - fatalError() + switch placePageData.mapNodeAttributes.nodeStatus { + case .downloading, .inQueue, .applying: + Storage.shared().cancelDownloadNode(placePageData.mapNodeAttributes.countryId) + case .notDownloaded, .partly, .error: + Storage.shared().downloadNode(placePageData.mapNodeAttributes.countryId) + case .undefined, .onDiskOutOfDate, .onDisk: + fatalError("Download button shouldn't be displayed when node is in these states") + @unknown default: + fatalError() + } case .opentable: fatalError("Opentable is not supported and will be deleted") case .partner: diff --git a/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.h b/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.h index 593ba9dee1..ca298b8277 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.h +++ b/iphone/Maps/UI/PlacePage/PlacePageLayout/ActionBar/MWMActionBarButton.h @@ -17,6 +17,8 @@ typedef NS_ENUM(NSInteger, MWMActionBarButtonType) { MWMActionBarButtonTypeAvoidFerry } NS_SWIFT_NAME(ActionBarButtonType); +NS_ASSUME_NONNULL_BEGIN + #ifdef __cplusplus extern "C" { #endif @@ -38,14 +40,16 @@ NS_SWIFT_NAME(ActionBarButtonDelegate) NS_SWIFT_NAME(ActionBarButton) @interface MWMActionBarButton : UIView +@property(nonatomic, readonly) MWMActionBarButtonType type; +@property(nonatomic, readonly, nullable) MWMCircularProgress *mapDownloadProgress; +@property(nonatomic, readonly) NSInteger partnerIndex; + + (MWMActionBarButton *)buttonWithDelegate:(id)delegate buttonType:(MWMActionBarButtonType)type partnerIndex:(NSInteger)partnerIndex isSelected:(BOOL)isSelected isDisabled:(BOOL)isDisabled; -- (MWMActionBarButtonType)type; -- (MWMCircularProgress *)mapDownloadProgress; -- (NSInteger)partnerIndex; - @end + +NS_ASSUME_NONNULL_END diff --git a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageCommonLayout.swift b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageCommonLayout.swift index b3466d3801..f50ab10e96 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageCommonLayout.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageCommonLayout.swift @@ -92,6 +92,7 @@ class PlacePageCommonLayout: NSObject, IPlacePageLayout { lazy var buttonsViewController: PlacePageButtonsViewController = { let vc = storyboard.instantiateViewController(ofType: PlacePageButtonsViewController.self) vc.buttonsData = placePageData.buttonsData! + vc.buttonsEnabled = placePageData.mapNodeAttributes.nodeStatus == .onDisk vc.delegate = interactor return vc } () @@ -205,6 +206,21 @@ class PlacePageCommonLayout: NSObject, IPlacePageLayout { onHeadingUpdate(lastHeading) } + placePageData.onMapNodeStatusUpdate = { [weak self] in + guard let self = self else { return } + self.actionBarViewController.updateDownloadButtonState(self.placePageData.mapNodeAttributes.nodeStatus) + if self.placePageData.mapNodeAttributes.nodeStatus == .onDisk { + self.actionBarViewController.resetButtons() + if self.placePageData.buttonsData != nil { + self.buttonsViewController.buttonsEnabled = true + } + } + } + placePageData.onMapNodeProgressUpdate = { [weak self] (downloadedBytes, totalBytes) in + guard let self = self, let downloadButton = self.actionBarViewController.downloadButton else { return } + downloadButton.mapDownloadProgress?.progress = CGFloat(downloadedBytes) / CGFloat(totalBytes) + } + return viewControllers } diff --git a/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm b/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm index 35a2380b82..de6aa99d6c 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm +++ b/iphone/Maps/UI/PlacePage/PlacePageManager/MWMPlacePageManager.mm @@ -1,7 +1,6 @@ #import "MWMPlacePageManager.h" #import "CLLocation+Mercator.h" #import "MWMActivityViewController.h" -#import "MWMFrameworkStorageObserver.h" #import "MWMLocationHelpers.h" #import "MWMLocationObserver.h" #import "MWMRoutePoint+CPP.h" diff --git a/iphone/Maps/UI/Search/MWMSearchManager.mm b/iphone/Maps/UI/Search/MWMSearchManager.mm index b14efd957a..c9964eb1d7 100644 --- a/iphone/Maps/UI/Search/MWMSearchManager.mm +++ b/iphone/Maps/UI/Search/MWMSearchManager.mm @@ -1,6 +1,5 @@ #import "MWMSearchManager.h" #import "MWMFrameworkListener.h" -#import "MWMFrameworkStorageObserver.h" #import "MWMMapViewControlsManager.h" #import "MWMNoMapsViewController.h" #import "MWMRoutePoint+CPP.h" @@ -31,7 +30,7 @@ using Observers = NSHashTable; @end @interface MWMSearchManager () + UITextFieldDelegate, MWMStorageObserver, MWMSearchObserver> @property(weak, nonatomic, readonly) UIViewController * ownerController; @@ -179,7 +178,7 @@ using Observers = NSHashTable; self.state = MWMSearchManagerStateHidden; } -#pragma mark - MWMFrameworkStorageObserver +#pragma mark - MWMStorageObserver - (void)processCountryEvent:(NSString *)countryId { @@ -369,7 +368,7 @@ using Observers = NSHashTable; - (UIViewController *)topController { - [MWMFrameworkListener removeObserver:self]; + [[MWMStorage sharedStorage] removeObserver:self]; self.noMapsController = nil; switch (self.state) { @@ -382,7 +381,7 @@ using Observers = NSHashTable; return tabViewController; } self.noMapsController = [MWMNoMapsViewController controller]; - [MWMFrameworkListener addObserver:self]; + [[MWMStorage sharedStorage] addObserver:self]; return self.noMapsController; } case MWMSearchManagerStateTableSearch: return self.tableViewController;