diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm index dae70992a6..5a5f19be23 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/BottomMenu/MWMBottomMenuViewController.mm @@ -15,6 +15,7 @@ #import "MWMSearchManager.h" #import "MWMSettingsViewController.h" #import "MWMTextToSpeech.h" +#import "MWMTrafficManager.h" #import "MapViewController.h" #import "MapsAppDelegate.h" #import "Statistics.h" @@ -58,7 +59,8 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) { @end -@interface MWMBottomMenuViewController () +@interface MWMBottomMenuViewController () @property(weak, nonatomic) MapViewController * controller; @property(weak, nonatomic) IBOutlet UICollectionView * buttonsCollectionView; @@ -143,6 +145,7 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) { selector:@selector(ttsButtonStatusChanged:) name:[MWMTextToSpeech ttsStatusNotificationKey] object:nil]; + [MWMTrafficManager addObserver:self]; } - (void)viewWillAppear:(BOOL)animated @@ -230,12 +233,22 @@ typedef NS_ENUM(NSUInteger, MWMBottomMenuViewCell) { [MWMTextToSpeech tts].active = isEnable; [self refreshRoutingDiminishTimer]; } + +#pragma mark - MWMTrafficManagerObserver + +- (void)onTrafficStateUpdated +{ + MWMButton * tb = self.trafficButton; + BOOL const enabled = ([MWMTrafficManager state] != TrafficManager::TrafficState::Disabled); + tb.coloring = enabled ? MWMButtonColoringBlue : MWMButtonColoringGray; + tb.selected = enabled; +} + - (IBAction)trafficTouchUpInside:(MWMButton *)sender { - BOOL const isEnable = sender.selected; - [Statistics logEvent:kStatMenu withParameters:@{kStatTraffic : isEnable ? kStatOn : kStatOff}]; - sender.coloring = isEnable ? MWMButtonColoringBlue : MWMButtonColoringGray; - sender.selected = !isEnable; // TODO: Replace with real logic + BOOL const switchOn = ([MWMTrafficManager state] == TrafficManager::TrafficState::Disabled); + [Statistics logEvent:kStatMenu withParameters:@{kStatTraffic : switchOn ? kStatOn : kStatOff}]; + [MWMTrafficManager enableTraffic:switchOn]; [self refreshRoutingDiminishTimer]; } diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/TrafficButton/MWMTrafficButtonViewController.mm b/iphone/Maps/Classes/CustomViews/MapViewControls/TrafficButton/MWMTrafficButtonViewController.mm index a58b593570..3cc1462bc3 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/TrafficButton/MWMTrafficButtonViewController.mm +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/TrafficButton/MWMTrafficButtonViewController.mm @@ -1,21 +1,31 @@ #import "MWMTrafficButtonViewController.h" #import "Common.h" +#import "MWMAlertViewController.h" #import "MWMButton.h" #import "MWMMapViewControlsCommon.h" #import "MWMMapViewControlsManager.h" +#import "MWMToast.h" +#import "MWMTrafficManager.h" #import "MapViewController.h" #import "UIColor+MapsMeColor.h" -typedef NS_ENUM(NSUInteger, MWMTrafficButtonState) { - MWMTrafficButtonStateOff, - MWMTrafficButtonStateOn, - MWMTrafficButtonStateUpdate -}; - namespace { CGFloat const kTopOffset = 26; CGFloat const kTopShiftedOffset = 6; + +NSArray * imagesWithName(NSString * name) +{ + NSUInteger const imagesCount = 3; + NSMutableArray * images = [NSMutableArray arrayWithCapacity:imagesCount]; + NSString * mode = [UIColor isNightMode] ? @"dark" : @"light"; + for (NSUInteger i = 1; i <= imagesCount; i += 1) + { + NSString * imageName = [NSString stringWithFormat:@"%@_%@_%@", name, mode, @(i).stringValue]; + [images addObject:static_cast([UIImage imageNamed:imageName])]; + } + return [images copy]; +} } // namespace @interface MWMMapViewControlsManager () @@ -24,11 +34,10 @@ CGFloat const kTopShiftedOffset = 6; @end -@interface MWMTrafficButtonViewController () +@interface MWMTrafficButtonViewController () @property(nonatomic) NSLayoutConstraint * topOffset; @property(nonatomic) NSLayoutConstraint * leftOffset; -@property(nonatomic) MWMTrafficButtonState state; @end @@ -48,7 +57,7 @@ CGFloat const kTopShiftedOffset = 6; [ovc addChildViewController:self]; [ovc.view addSubview:self.view]; [self configLayout]; - self.state = MWMTrafficButtonStateOff; + [MWMTrafficManager addObserver:self]; } return self; } @@ -110,12 +119,6 @@ CGFloat const kTopShiftedOffset = 6; [self refreshLayout]; } -- (void)setState:(MWMTrafficButtonState)state -{ - _state = state; - [self refreshAppearance]; -} - - (void)refreshLayout { runAsyncOnMainQueue(^{ @@ -136,29 +139,43 @@ CGFloat const kTopShiftedOffset = 6; - (void)refreshAppearance { MWMButton * btn = static_cast(self.view); - switch (self.state) + UIImageView * iv = btn.imageView; + [iv stopAnimating]; + switch ([MWMTrafficManager state]) { - case MWMTrafficButtonStateOff: btn.imageName = @"btn_traffic_off"; break; - case MWMTrafficButtonStateOn: btn.imageName = @"btn_traffic_on"; break; - case MWMTrafficButtonStateUpdate: - { - NSUInteger const imagesCount = 3; - NSMutableArray * images = [NSMutableArray arrayWithCapacity:imagesCount]; - NSString * mode = [UIColor isNightMode] ? @"dark" : @"light"; - for (NSUInteger i = 1; i <= imagesCount; i += 1) - { - NSString * name = - [NSString stringWithFormat:@"btn_traffic_update_%@_%@", mode, @(i).stringValue]; - [images addObject:[UIImage imageNamed:name]]; - } - UIImageView * iv = btn.imageView; - iv.animationImages = images; + case TrafficManager::TrafficState::Disabled: btn.imageName = @"btn_traffic_off"; break; + case TrafficManager::TrafficState::Enabled: btn.imageName = @"btn_traffic_on"; break; + case TrafficManager::TrafficState::WaitingData: + iv.animationImages = imagesWithName(@"btn_traffic_update"); iv.animationDuration = 0.8; - iv.image = images.lastObject; + iv.image = iv.animationImages.lastObject; [iv startAnimating]; break; - } + case TrafficManager::TrafficState::Outdated: btn.imageName = @"btn_traffic_outdated"; break; + case TrafficManager::TrafficState::NetworkError: + [MWMTrafficManager enableTraffic:NO]; + [[MWMAlertViewController activeAlertController] presentNoConnectionAlert]; + break; + case TrafficManager::TrafficState::NoData: + [MWMToast showWithText:L(@"traffic_state_no_data")]; + break; + case TrafficManager::TrafficState::ExpiredApp: + [MWMToast showWithText:L(@"traffic_state_expired_app")]; + break; + case TrafficManager::TrafficState::ExpiredData: + [MWMToast showWithText:L(@"traffic_state_expired_data")]; + break; } } +- (IBAction)buttonTouchUpInside +{ + if ([MWMTrafficManager state] == TrafficManager::TrafficState::Disabled) + [MWMTrafficManager enableTraffic:YES]; + else + [MWMTrafficManager enableTraffic:NO]; +} +#pragma mark - MWMTrafficManagerObserver + +- (void)onTrafficStateUpdated { [self refreshAppearance]; } @end diff --git a/iphone/Maps/Classes/CustomViews/MapViewControls/TrafficButton/MWMTrafficButtonViewController.xib b/iphone/Maps/Classes/CustomViews/MapViewControls/TrafficButton/MWMTrafficButtonViewController.xib index d498ba4a9a..47256ff3af 100644 --- a/iphone/Maps/Classes/CustomViews/MapViewControls/TrafficButton/MWMTrafficButtonViewController.xib +++ b/iphone/Maps/Classes/CustomViews/MapViewControls/TrafficButton/MWMTrafficButtonViewController.xib @@ -22,7 +22,10 @@ - + + + + diff --git a/iphone/Maps/Classes/TrafficManager/MWMTrafficManager.h b/iphone/Maps/Classes/TrafficManager/MWMTrafficManager.h new file mode 100644 index 0000000000..f36ec68392 --- /dev/null +++ b/iphone/Maps/Classes/TrafficManager/MWMTrafficManager.h @@ -0,0 +1,14 @@ +#import "MWMTrafficManagerObserver.h" + +#include "map/traffic_manager.hpp" + +@interface MWMTrafficManager : NSObject + ++ (void)addObserver:(id)observer; ++ (void)removeObserver:(id)observer; + ++ (TrafficManager::TrafficState)state; + ++ (void)enableTraffic:(BOOL)enable; + +@end diff --git a/iphone/Maps/Classes/TrafficManager/MWMTrafficManager.mm b/iphone/Maps/Classes/TrafficManager/MWMTrafficManager.mm new file mode 100644 index 0000000000..e3c2dda5d3 --- /dev/null +++ b/iphone/Maps/Classes/TrafficManager/MWMTrafficManager.mm @@ -0,0 +1,72 @@ +#import "MWMTrafficManager.h" +#import "Common.h" + +#include "Framework.h" + +namespace +{ +using TObserver = id; +using TObservers = NSHashTable<__kindof TObserver>; +} // namespace + +@interface MWMTrafficManager () + +@property(nonatomic) TObservers * observers; + +@property(nonatomic) TrafficManager::TrafficState state; + +@end + +@implementation MWMTrafficManager + +#pragma mark - Instance + ++ (MWMTrafficManager *)manager +{ + static MWMTrafficManager * manager; + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + manager = [[super alloc] initManager]; + }); + return manager; +} + +- (instancetype)initManager +{ + self = [super init]; + if (self) + { + _observers = [TObservers weakObjectsHashTable]; + auto & m = GetFramework().GetTrafficManager(); + m.SetStateListener([self](TrafficManager::TrafficState state) { + runAsyncOnMainQueue(^{ + self.state = state; + for (TObserver observer in self.observers) + [observer onTrafficStateUpdated]; + }); + }); + } + return self; +} + +#pragma mark - Add/Remove Observers + ++ (void)addObserver:(TObserver)observer +{ + [[MWMTrafficManager manager].observers addObject:observer]; +} + ++ (void)removeObserver:(TObserver)observer +{ + [[MWMTrafficManager manager].observers removeObject:observer]; +} + ++ (TrafficManager::TrafficState)state { return [MWMTrafficManager manager].state; } ++ (void)enableTraffic:(BOOL)enable +{ + auto & f = GetFramework(); + f.GetTrafficManager().SetEnabled(enable); + f.SaveTrafficEnabled(enable); +} + +@end diff --git a/iphone/Maps/Classes/TrafficManager/MWMTrafficManagerObserver.h b/iphone/Maps/Classes/TrafficManager/MWMTrafficManagerObserver.h new file mode 100644 index 0000000000..0a5a724292 --- /dev/null +++ b/iphone/Maps/Classes/TrafficManager/MWMTrafficManagerObserver.h @@ -0,0 +1,5 @@ +@protocol MWMTrafficManagerObserver + +- (void)onTrafficStateUpdated; + +@end diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index d55cf21efc..acead740a7 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -34,6 +34,9 @@ 3406FA191C6E0D8F00E9FAD2 /* MWMMapDownloadDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3406FA171C6E0D8F00E9FAD2 /* MWMMapDownloadDialog.xib */; }; 340837131B7243CE00B5C185 /* MWMActivityViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 340837121B7243CE00B5C185 /* MWMActivityViewController.mm */; }; 340837161B72451A00B5C185 /* MWMShareActivityItem.mm in Sources */ = {isa = PBXBuildFile; fileRef = 340837151B72451A00B5C185 /* MWMShareActivityItem.mm */; }; + 34094F281DF1C1E7005F7A22 /* MWMTrafficManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34094F231DF1C1E7005F7A22 /* MWMTrafficManager.mm */; }; + 34094F291DF1C1E7005F7A22 /* MWMTrafficManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34094F231DF1C1E7005F7A22 /* MWMTrafficManager.mm */; }; + 34094F2A1DF1C1E7005F7A22 /* MWMTrafficManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34094F231DF1C1E7005F7A22 /* MWMTrafficManager.mm */; }; 340C20E31C3E565600111D22 /* MWMCuisineEditorViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 340C20E21C3E565600111D22 /* MWMCuisineEditorViewController.mm */; }; 340C20E41C3E565600111D22 /* MWMCuisineEditorViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 340C20E21C3E565600111D22 /* MWMCuisineEditorViewController.mm */; }; 340E10601B944DAB00D975D5 /* MWMSearchHistoryManager.mm in Sources */ = {isa = PBXBuildFile; fileRef = 340E105F1B944DAB00D975D5 /* MWMSearchHistoryManager.mm */; }; @@ -1430,6 +1433,9 @@ 340837121B7243CE00B5C185 /* MWMActivityViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMActivityViewController.mm; sourceTree = ""; }; 340837141B72451A00B5C185 /* MWMShareActivityItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMShareActivityItem.h; sourceTree = ""; }; 340837151B72451A00B5C185 /* MWMShareActivityItem.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMShareActivityItem.mm; sourceTree = ""; }; + 34094F211DF1C1E7005F7A22 /* MWMTrafficManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMTrafficManager.h; sourceTree = ""; }; + 34094F231DF1C1E7005F7A22 /* MWMTrafficManager.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMTrafficManager.mm; sourceTree = ""; }; + 34094F241DF1C1E7005F7A22 /* MWMTrafficManagerObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMTrafficManagerObserver.h; sourceTree = ""; }; 340C20E11C3E565600111D22 /* MWMCuisineEditorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMCuisineEditorViewController.h; sourceTree = ""; }; 340C20E21C3E565600111D22 /* MWMCuisineEditorViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = MWMCuisineEditorViewController.mm; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 340C20E51C3E58B000111D22 /* MWMEditorCommon.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMEditorCommon.h; sourceTree = ""; }; @@ -2390,6 +2396,7 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 34094F201DF1C1E7005F7A22 /* TrafficManager */, 34EA97691DEC779D00616B11 /* NetworkPolicy */, 348868F01D87DF8C0069BBA3 /* Keyboard */, 3436FE7F1D366CA0005CD87B /* Search */, @@ -2557,6 +2564,16 @@ path = Share; sourceTree = ""; }; + 34094F201DF1C1E7005F7A22 /* TrafficManager */ = { + isa = PBXGroup; + children = ( + 34094F211DF1C1E7005F7A22 /* MWMTrafficManager.h */, + 34094F231DF1C1E7005F7A22 /* MWMTrafficManager.mm */, + 34094F241DF1C1E7005F7A22 /* MWMTrafficManagerObserver.h */, + ); + path = TrafficManager; + sourceTree = ""; + }; 340C20E01C3E563500111D22 /* Cuisine */ = { isa = PBXGroup; children = ( @@ -4744,6 +4761,7 @@ 34C9BD021C6DB693000DC38D /* MWMTableViewController.mm in Sources */, F63BA3711BCD5B520044C504 /* MWMTTSLanguageViewController.mm in Sources */, F64DA8021C524BDE00330E9E /* UISwitch+RuntimeAttributes.m in Sources */, + 34094F281DF1C1E7005F7A22 /* MWMTrafficManager.mm in Sources */, F607C18E1C047FDC00B53A87 /* MWMSegue.mm in Sources */, 34DCDE3A1C75CD8100652CAC /* Framework.cpp in Sources */, 341138801C15B50B002E3B3E /* MWMOpeningHoursModel.mm in Sources */, @@ -4996,6 +5014,7 @@ 6741A9D51BF340DE002C974C /* WebViewController.mm in Sources */, 34C9BD031C6DB693000DC38D /* MWMTableViewController.mm in Sources */, 34AA7DA01D63543E00254037 /* MWMRouterSavedState.mm in Sources */, + 34094F291DF1C1E7005F7A22 /* MWMTrafficManager.mm in Sources */, F64DA8031C52520000330E9E /* UISwitch+RuntimeAttributes.m in Sources */, 676507631C1055BB00830BB3 /* MWMTTSLanguageViewController.mm in Sources */, 341138811C15B50B002E3B3E /* MWMOpeningHoursModel.mm in Sources */, @@ -5344,6 +5363,7 @@ 849CF7351DE842290024A8A5 /* MWMSearchCategoriesManager.mm in Sources */, 849CF7361DE842290024A8A5 /* MWMStorage.mm in Sources */, 849CF7371DE842290024A8A5 /* MWMTaxiCollectionLayout.mm in Sources */, + 34094F2A1DF1C1E7005F7A22 /* MWMTrafficManager.mm in Sources */, 849CF7381DE842290024A8A5 /* MWMPPPreviewLayoutHelper.mm in Sources */, 849CF7391DE842290024A8A5 /* UIColor+MapsMeColor.mm in Sources */, 849CF73A1DE842290024A8A5 /* MWMOpeningHours.mm in Sources */,