From 72740cd15dae576de1de90dc6f972e10b90994b2 Mon Sep 17 00:00:00 2001 From: Ilya Grechuhin Date: Wed, 27 May 2015 11:01:23 +0300 Subject: [PATCH] [ios] Restore active routing. --- iphone/Maps/Classes/MapViewController.h | 3 +- iphone/Maps/Classes/MapViewController.mm | 54 ++++++++++--- iphone/Maps/Classes/MapsAppDelegate.mm | 21 +++++ iphone/Maps/Classes/RouteState/RouteState.h | 23 ++++++ iphone/Maps/Classes/RouteState/RouteState.mm | 80 ++++++++++++++++++++ iphone/Maps/Maps.xcodeproj/project.pbxproj | 16 ++++ map/framework.cpp | 25 ------ map/framework.hpp | 11 +-- map/routing_session.cpp | 15 ---- map/routing_session.hpp | 7 +- 10 files changed, 195 insertions(+), 60 deletions(-) create mode 100644 iphone/Maps/Classes/RouteState/RouteState.h create mode 100644 iphone/Maps/Classes/RouteState/RouteState.mm diff --git a/iphone/Maps/Classes/MapViewController.h b/iphone/Maps/Classes/MapViewController.h index 4438ce814d..3f32c5b57a 100644 --- a/iphone/Maps/Classes/MapViewController.h +++ b/iphone/Maps/Classes/MapViewController.h @@ -43,8 +43,6 @@ namespace search { struct AddressInfo; } - (void)onEnterForeground; - (void)onEnterBackground; -- (IBAction)onMyPositionClicked:(id)sender; - - (void)dismissPopover; - (void)setMapStyle:(MapStyle)mapStyle; @@ -55,5 +53,6 @@ namespace search { struct AddressInfo; } @property (nonatomic) ShareActionSheet * shareActionSheet; - (void)setApiMode:(BOOL)apiMode animated:(BOOL)animated; @property (nonatomic, readonly) MWMMapViewControlsManager * controlsManager; +@property (nonatomic) m2::PointD restoreRouteDestination; @end diff --git a/iphone/Maps/Classes/MapViewController.mm b/iphone/Maps/Classes/MapViewController.mm index d4b357ac1a..9171b841b3 100644 --- a/iphone/Maps/Classes/MapViewController.mm +++ b/iphone/Maps/Classes/MapViewController.mm @@ -15,6 +15,7 @@ #import "MWMMapViewControlsManager.h" #import "../../../3party/Alohalytics/src/alohalytics_objc.h" #import "../../Common/CustomAlertView.h" +#import "RouteState.h" #include "Framework.h" #include "RenderContext.hpp" @@ -36,6 +37,13 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; +typedef NS_ENUM(NSUInteger, ForceRoutingStateChange) +{ + ForceRoutingStateChangeNone, + ForceRoutingStateChangeRestoreRoute, + ForceRoutingStateChangeStartFollowing +}; + @interface NSValueWrapper : NSObject -(NSValue *)getInnerValue; @@ -78,6 +86,8 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; @property (nonatomic) UILabel * apiTitleLabel; @property (nonatomic, readwrite) MWMMapViewControlsManager * controlsManager; +@property (nonatomic) ForceRoutingStateChange forceRoutingStateChange; + @end @implementation MapViewController @@ -132,6 +142,9 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; [self showPopover]; [self updateRoutingInfo]; + + if (self.forceRoutingStateChange == ForceRoutingStateChangeRestoreRoute) + [self restoreRoute]; } } @@ -231,6 +244,14 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; } } +#pragma mark - Restore route + +- (void)restoreRoute +{ + GetFramework().BuildRoute(self.restoreRouteDestination); + self.forceRoutingStateChange = ForceRoutingStateChangeStartFollowing; +} + #pragma mark - Map Navigation - (void)dismissPlacePage @@ -247,11 +268,6 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; } } -- (void)onMyPositionClicked:(id)sender -{ - GetFramework().GetLocationState()->SwitchToNextMode(); -} - - (void)processMapClickAtPoint:(CGPoint)point longClick:(BOOL)isLongClick { CGFloat const scaleFactor = self.view.contentScaleFactor; @@ -647,6 +663,8 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; EAGLView * v = (EAGLView *)self.view; [v initRenderPolicy]; + + self.forceRoutingStateChange = ForceRoutingStateChangeNone; // restore previous screen position if (!f.LoadState()) @@ -700,14 +718,20 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; { [self.containerView.placePage showBuildingRoutingActivity:NO]; - switch (code) { - case routing::IRouter::ResultCode::NoError: { + switch (code) + { + case routing::IRouter::ResultCode::NoError: + { f.GetBalloonManager().RemovePin(); f.GetBalloonManager().Dismiss(); [self.containerView.placePage setState:PlacePageStateHidden animated:YES withCallback:YES]; [self.searchView setState:SearchViewStateHidden animated:YES withCallback:YES]; - [self performAfterDelay:0.3 block:^{ - [self.routeView setState:RouteViewStateInfo animated:YES]; + [self performAfterDelay:0.3 block:^ + { + if (self.forceRoutingStateChange == ForceRoutingStateChangeStartFollowing) + [self routeViewDidStartFollowing:self.routeView]; + else + [self.routeView setState:RouteViewStateInfo animated:YES]; [self updateRoutingInfo]; }]; @@ -717,7 +741,7 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; { NSString * title; NSString * message; - if (SYSTEM_VERSION_IS_LESS_THAN(@"7.0")) + if (isIOSVersionLessThan(7)) message = L(@"routing_disclaimer"); else title = L(@"routing_disclaimer"); @@ -907,6 +931,7 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; [routeView setState:RouteViewStateTurnInstructions animated:YES]; self.controlsManager.zoomHidden = NO; GetFramework().FollowRoute(); + [RouteState save]; } - (void)routeViewDidCancelRouting:(RouteView *)routeView @@ -924,6 +949,7 @@ extern NSString * const kAlohalyticsTapEventKey = @"$onClick"; GetFramework().CloseRouting(); [self.controlsManager resetZoomButtonsVisibility]; [self.routeView setState:RouteViewStateHidden animated:YES]; + [RouteState remove]; } #pragma mark - PlacePageViewDelegate @@ -1219,4 +1245,12 @@ NSInteger compareAddress(id l, id r, void * context) [self invalidate]; } +#pragma mark - Properties + +- (void)setRestoreRouteDestination:(m2::PointD)restoreRouteDestination +{ + _restoreRouteDestination = restoreRouteDestination; + self.forceRoutingStateChange = ForceRoutingStateChangeRestoreRoute; +} + @end diff --git a/iphone/Maps/Classes/MapsAppDelegate.mm b/iphone/Maps/Classes/MapsAppDelegate.mm index 2cc217cf50..01466d01a3 100644 --- a/iphone/Maps/Classes/MapsAppDelegate.mm +++ b/iphone/Maps/Classes/MapsAppDelegate.mm @@ -10,6 +10,7 @@ #import "Reachability.h" #import "MWMWatchEventInfo.h" #import "Common.h" +#import "RouteState.h" #include @@ -240,6 +241,11 @@ void InitLocalizedStrings() } } +- (void)applicationWillResignActive:(UIApplication *)application +{ + [RouteState save]; +} + - (void)applicationWillEnterForeground:(UIApplication *)application { [self.m_locationManager orientationChanged]; @@ -297,6 +303,8 @@ void InitLocalizedStrings() if (!isIOSVersionLessThan(7)) [FBSDKAppEvents activateApp]; + + [self restoreRouteState]; } - (void)dealloc @@ -491,6 +499,19 @@ void InitLocalizedStrings() } } +#pragma mark - Route state + +- (void)restoreRouteState +{ + if (GetFramework().IsRoutingActive()) + return; + RouteState const * const state = [RouteState savedState]; + if (state.hasActualRoute) + self.m_mapViewController.restoreRouteDestination = state.endPoint; + else + [RouteState remove]; +} + #pragma mark - Alert logic - (void)firstLaunchSetup diff --git a/iphone/Maps/Classes/RouteState/RouteState.h b/iphone/Maps/Classes/RouteState/RouteState.h new file mode 100644 index 0000000000..87f177a4fc --- /dev/null +++ b/iphone/Maps/Classes/RouteState/RouteState.h @@ -0,0 +1,23 @@ +// +// RouteState.h +// Maps +// +// Created by Ilya Grechuhin on 26.05.15. +// Copyright (c) 2015 MapsWithMe. All rights reserved. +// + +#import + +#include + +@interface RouteState : NSObject + +@property (nonatomic, readonly) BOOL hasActualRoute; +@property (nonatomic) m2::PointD endPoint; + ++ (instancetype)savedState; + ++ (void)save; ++ (void)remove; + +@end diff --git a/iphone/Maps/Classes/RouteState/RouteState.mm b/iphone/Maps/Classes/RouteState/RouteState.mm new file mode 100644 index 0000000000..f01d162e63 --- /dev/null +++ b/iphone/Maps/Classes/RouteState/RouteState.mm @@ -0,0 +1,80 @@ +// +// RouteState.m +// Maps +// +// Created by Ilya Grechuhin on 26.05.15. +// Copyright (c) 2015 MapsWithMe. All rights reserved. +// + +#import "RouteState.h" +#import "Framework.h" + +static NSString * const kEndPointKey = @"endPoint"; +static NSString * const kETAKey = @"eta"; + +@interface RouteState() + +@property (nonatomic) NSDate * eta; + +@end + +@implementation RouteState + ++ (instancetype)savedState +{ + RouteState * const state = [[super alloc] init]; + if (state) + { + NSDictionary * const stateDict = [NSDictionary dictionaryWithContentsOfURL:[RouteState stateFileURL]]; + if (stateDict) + { + m2::PointD point; + NSUInteger size; + NSGetSizeAndAlignment(@encode(m2::PointD), &size, NULL); + NSData const * const endPointData = stateDict[kEndPointKey]; + NSDate * const eta = stateDict[kETAKey]; + if (endPointData && eta) + { + [endPointData getBytes:&point length:size]; + state.endPoint = point; + state.eta = eta; + } + } + } + return state; +} + ++ (void)save +{ + Framework & f = GetFramework(); + if (!f.IsRoutingActive()) + return; + location::FollowingInfo routeInfo; + f.GetRouteFollowingInfo(routeInfo); + m2::PointD const endPoint = f.GetRouteEndPoint(); + NSMutableDictionary * const stateDict = [NSMutableDictionary dictionary]; + NSUInteger size; + NSGetSizeAndAlignment(@encode(m2::PointD), &size, nullptr); + stateDict[kEndPointKey] = [NSData dataWithBytes:&endPoint length:size]; + stateDict[kETAKey] = [NSDate dateWithTimeIntervalSinceNow:routeInfo.m_time]; + [stateDict writeToURL:[RouteState stateFileURL] atomically:YES]; +} + ++ (void)remove +{ + [[NSFileManager defaultManager] removeItemAtURL:[RouteState stateFileURL] error:nil]; +} + ++ (NSURL *)stateFileURL +{ + return [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"route_info.ini"]]; +} + +#pragma mark - Properties + +- (BOOL)hasActualRoute +{ + return [self.eta compare:[NSDate date]] == NSOrderedDescending; +} + +@end diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index a410251906..551ceace2c 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 288765080DF74369002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765070DF74369002DB57D /* CoreGraphics.framework */; }; 28AD73880D9D96C1002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD73870D9D96C1002E5188 /* MainWindow.xib */; }; + 340F24631B14910500F874CD /* RouteState.mm in Sources */ = {isa = PBXBuildFile; fileRef = 340F24621B14910500F874CD /* RouteState.mm */; }; 343F262E1AEFC4A300388A6D /* MWMFrameworkUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 343F262D1AEFC4A300388A6D /* MWMFrameworkUtils.mm */; }; 343F26301AEFDB1A00388A6D /* Framework.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 343F262F1AEFDB1A00388A6D /* Framework.cpp */; }; 343F26311AEFDF3E00388A6D /* resources-xhdpi in Resources */ = {isa = PBXBuildFile; fileRef = 97FC99DA19C1A2CD00C1CF98 /* resources-xhdpi */; }; @@ -314,6 +315,8 @@ 28AD73870D9D96C1002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = SOURCE_ROOT; }; 29B97316FDCFA39411CA2CEA /* main.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = main.mm; sourceTree = ""; }; 340F24641B15F01D00F874CD /* MWMSideMenuDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMSideMenuDelegate.h; sourceTree = ""; }; + 340F24611B14910500F874CD /* RouteState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RouteState.h; sourceTree = ""; }; + 340F24621B14910500F874CD /* RouteState.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RouteState.mm; sourceTree = ""; }; 343F262C1AEFC4A300388A6D /* MWMFrameworkUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MWMFrameworkUtils.h; sourceTree = ""; }; 343F262D1AEFC4A300388A6D /* MWMFrameworkUtils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMFrameworkUtils.mm; sourceTree = ""; }; 343F262F1AEFDB1A00388A6D /* Framework.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Framework.cpp; path = ../../Classes/Framework.cpp; sourceTree = ""; }; @@ -746,6 +749,7 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( + 340F24601B1490ED00F874CD /* RouteState */, F62A73A71AD8950900175470 /* WatchEventHandler */, F64F195F1AB8125C006EAF7E /* CustomAlert */, 97B4E9271851DAB300BEC5D7 /* Custom Views */, @@ -886,6 +890,15 @@ name = Frameworks; sourceTree = ""; }; + 340F24601B1490ED00F874CD /* RouteState */ = { + isa = PBXGroup; + children = ( + 340F24611B14910500F874CD /* RouteState.h */, + 340F24621B14910500F874CD /* RouteState.mm */, + ); + path = RouteState; + sourceTree = ""; + }; 343F262B1AEFC4A300388A6D /* FrameworkUtils */ = { isa = PBXGroup; children = ( @@ -1896,6 +1909,7 @@ FAFCB63613366E78001A5C59 /* WebViewController.mm in Sources */, 34BC72221B0DECAE0012A34B /* MWMLocationButtonView.mm in Sources */, FA34BECA1338D72F00FFB2A7 /* CustomAlertView.mm in Sources */, + 340F24631B14910500F874CD /* RouteState.mm in Sources */, 97F61781183E6172009919E2 /* LocationButton.mm in Sources */, 9747264318323080006B7CB7 /* UIKitCategories.m in Sources */, 977E26BE19E31BBE00BA2219 /* CountryTreeVC.mm in Sources */, @@ -2209,6 +2223,7 @@ "$(PROJECT_DIR)/MyTracker", "$(PROJECT_DIR)/Statistics", ); + ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-Wall"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", @@ -2797,6 +2812,7 @@ "$(PROJECT_DIR)/MyTracker", "$(PROJECT_DIR)/Statistics", ); + ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = "-Wall"; OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)"; OTHER_LDFLAGS = ( diff --git a/map/framework.cpp b/map/framework.cpp index 1f354b74e6..df9287b179 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2174,16 +2174,6 @@ void Framework::UpdateSavedDataVersion() Settings::Set("DataVersion", m_storage.GetCurrentDataVersion()); } -bool Framework::IsRoutingActive() const -{ - return m_routingSession.IsActive(); -} - -bool Framework::IsRouteBuilt() const -{ - return m_routingSession.IsBuilt(); -} - void Framework::BuildRoute(m2::PointD const & destination) { shared_ptr const & state = GetLocationState(); @@ -2217,16 +2207,6 @@ void Framework::BuildRoute(m2::PointD const & destination) }); } -void Framework::SetRouteBuildingListener(TRouteBuildingCallback const & callback) -{ - m_routingCallback = callback; -} - -void Framework::FollowRoute() -{ - GetLocationState()->StartRouteFollow(); -} - void Framework::SetRouter(RouterType type) { #ifdef DEBUG @@ -2373,8 +2353,3 @@ string Framework::GetRoutingErrorMessage(IRouter::ResultCode code) return m_stringsBundle.GetString(messageID); } - -void Framework::GetRouteFollowingInfo(location::FollowingInfo & info) const -{ - m_routingSession.GetRouteFollowingInfo(info); -} diff --git a/map/framework.hpp b/map/framework.hpp index e2383ea81d..6171a4cde4 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -564,14 +564,15 @@ public: public: /// @name Routing mode //@{ - bool IsRoutingActive() const; - bool IsRouteBuilt() const; + bool IsRoutingActive() const { return m_routingSession.IsActive(); } + bool IsRouteBuilt() const { return m_routingSession.IsBuilt(); } void BuildRoute(m2::PointD const & destination); typedef function const &)> TRouteBuildingCallback; - void SetRouteBuildingListener(TRouteBuildingCallback const & callback); - void FollowRoute(); + void SetRouteBuildingListener(TRouteBuildingCallback const & callback) { m_routingCallback = callback; } + void FollowRoute() { GetLocationState()->StartRouteFollow(); } void CloseRouting(); - void GetRouteFollowingInfo(location::FollowingInfo & info) const; + void GetRouteFollowingInfo(location::FollowingInfo & info) const { m_routingSession.GetRouteFollowingInfo(info); } + m2::PointD GetRouteEndPoint() const { return m_routingSession.GetEndPoint(); } private: void SetRouter(routing::RouterType type); diff --git a/map/routing_session.cpp b/map/routing_session.cpp index cef5f06f49..64aa286261 100644 --- a/map/routing_session.cpp +++ b/map/routing_session.cpp @@ -58,21 +58,6 @@ void RoutingSession::DoReadyCallback::operator() (Route & route, IRouter::Result m_callback(m_rs.m_route, e); } -bool RoutingSession::IsActive() const -{ - return (m_state != RoutingNotActive); -} - -bool RoutingSession::IsNavigable() const -{ - return (m_state == RouteNotStarted || m_state == OnRoute); -} - -bool RoutingSession::IsBuilt() const -{ - return (IsNavigable() || m_state == RouteNeedRebuild || m_state == RouteFinished); -} - void RoutingSession::Reset() { m_state = RoutingNotActive; diff --git a/map/routing_session.hpp b/map/routing_session.hpp index 2f900a0b9f..5453b35c14 100644 --- a/map/routing_session.hpp +++ b/map/routing_session.hpp @@ -58,9 +58,10 @@ public: void BuildRoute(m2::PointD const & startPoint, m2::PointD const & endPoint, TReadyCallbackFn const & callback); void RebuildRoute(m2::PointD const & startPoint, TReadyCallbackFn const & callback); - bool IsActive() const; - bool IsNavigable() const; - bool IsBuilt() const; + m2::PointD GetEndPoint() const { return m_endPoint; } + bool IsActive() const { return (m_state != RoutingNotActive); } + bool IsNavigable() const { return (m_state == RouteNotStarted || m_state == OnRoute); } + bool IsBuilt() const { return (IsNavigable() || m_state == RouteNeedRebuild || m_state == RouteFinished); } void Reset(); State OnLocationPositionChanged(m2::PointD const & position, location::GpsInfo const & info);