diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData+Core.h b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData+Core.h index 1de63adaa..894e6582c 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData+Core.h +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData+Core.h @@ -6,7 +6,8 @@ NS_ASSUME_NONNULL_BEGIN @interface PlacePageTrackData (Core) -- (instancetype)initWithTrack:(Track const &)track; +- (instancetype)initWithTrack:(Track const &)track + onActivePointChanged:(MWMVoidBlock)onActivePointChangedHandler; @end diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData.h b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData.h index fa83eb897..51aabd0e0 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData.h +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData.h @@ -12,8 +12,15 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, readonly) MWMMarkGroupID groupId; @property(nonatomic, readwrite, nonnull) TrackInfo * trackInfo; @property(nonatomic, readwrite, nullable) ElevationProfileData * elevationProfileData; +@property(nonatomic, readonly) double activePoint; +@property(nonatomic, readonly) double myPosition; +@property(nonatomic) MWMVoidBlock onActivePointChangedHandler; -- (instancetype)initWithTrackInfo:(TrackInfo * _Nonnull)trackInfo elevationInfo:(ElevationProfileData * _Nullable)elevationInfo; +- (instancetype)initWithTrackInfo:(TrackInfo *)trackInfo + elevationInfo:(ElevationProfileData * _Nullable)elevationInfo + onActivePointChanged:(MWMVoidBlock)onActivePointChangedHandler; + +- (void)updateActivePointDistance:(double)distance; @end diff --git a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData.mm b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData.mm index d8b4ff89f..c98d17e78 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData.mm +++ b/iphone/CoreApi/CoreApi/PlacePageData/Common/PlacePageTrackData.mm @@ -2,33 +2,52 @@ #import "ElevationProfileData+Core.h" #import "TrackInfo+Core.h" +@interface PlacePageTrackData () + +@property(nonatomic, readwrite) double activePoint; + +@end + @implementation PlacePageTrackData -- (nonnull instancetype)initWithTrackInfo:(TrackInfo *)trackInfo elevationInfo:(ElevationProfileData * _Nullable)elevationInfo { +- (instancetype)initWithTrackInfo:(TrackInfo *)trackInfo + elevationInfo:(ElevationProfileData * _Nullable)elevationInfo + onActivePointChanged:(MWMVoidBlock)onActivePointChangedHandler { self = [super init]; if (self) { _trackInfo = trackInfo; _elevationProfileData = elevationInfo; + _onActivePointChangedHandler = onActivePointChangedHandler; } return self; } +- (void)updateActivePointDistance:(double)distance { + self.activePoint = distance; + if (self.onActivePointChangedHandler) + self.onActivePointChangedHandler(); +} + @end @implementation PlacePageTrackData (Core) -- (instancetype)initWithTrack:(Track const &)track { +- (instancetype)initWithTrack:(Track const &)track + onActivePointChanged:(MWMVoidBlock)onActivePointChangedHandler { self = [super init]; if (self) { _trackId = track.GetData().m_id; _trackInfo = [[TrackInfo alloc] initWithTrackStatistics:track.GetStatistics()]; + + auto const & bm = GetFramework().GetBookmarkManager(); + _activePoint = bm.GetElevationActivePoint(_trackId); + _myPosition = bm.GetElevationMyPosition(_trackId); + _onActivePointChangedHandler = onActivePointChangedHandler; + auto const & elevationInfo = track.GetElevationInfo(); if (track.HasAltitudes() && elevationInfo.has_value()) { - auto const & bm = GetFramework().GetBookmarkManager(); _elevationProfileData = [[ElevationProfileData alloc] initWithTrackId:_trackId - elevationInfo:elevationInfo.value() - activePoint:bm.GetElevationActivePoint(_trackId) - myPosition:bm.GetElevationMyPosition(_trackId)]; + elevationInfo:elevationInfo.value()]; } } return self; diff --git a/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData+Core.h b/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData+Core.h index 0a00cabca..942fdcbe3 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData+Core.h +++ b/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData+Core.h @@ -8,9 +8,7 @@ NS_ASSUME_NONNULL_BEGIN @interface ElevationProfileData (Core) - (instancetype)initWithTrackId:(MWMTrackID)trackId - elevationInfo:(ElevationInfo const &)elevationInfo - activePoint:(double)activePoint - myPosition:(double)myPosition; + elevationInfo:(ElevationInfo const &)elevationInfo; - (instancetype)initWithElevationInfo:(ElevationInfo const &)elevationInfo; @end diff --git a/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData.h b/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData.h index 2087a30a2..f31fc696f 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData.h +++ b/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData.h @@ -16,8 +16,6 @@ typedef NS_ENUM(NSInteger, ElevationDifficulty) { @property(nonatomic, readonly) BOOL isTrackRecording; @property(nonatomic, readonly) ElevationDifficulty difficulty; @property(nonatomic, readonly) NSArray * points; -@property(nonatomic, readonly) double activePoint; -@property(nonatomic, readonly) double myPosition; @end diff --git a/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData.mm b/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData.mm index e09cfd38f..d7504fb07 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData.mm +++ b/iphone/CoreApi/CoreApi/PlacePageData/ElevationProfile/ElevationProfileData.mm @@ -23,16 +23,12 @@ static ElevationDifficulty convertDifficulty(uint8_t difficulty) { @implementation ElevationProfileData (Core) - (instancetype)initWithTrackId:(MWMTrackID)trackId - elevationInfo:(ElevationInfo const &)elevationInfo - activePoint:(double)activePoint - myPosition:(double)myPosition { + elevationInfo:(ElevationInfo const &)elevationInfo { self = [super init]; if (self) { _trackId = trackId; _difficulty = convertDifficulty(elevationInfo.GetDifficulty()); _points = [ElevationProfileData pointsFromElevationInfo:elevationInfo]; - _activePoint = activePoint; - _myPosition = myPosition; _isTrackRecording = false; } return self; diff --git a/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm b/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm index 491452b0a..c351621d1 100644 --- a/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm +++ b/iphone/CoreApi/CoreApi/PlacePageData/PlacePageData.mm @@ -32,6 +32,9 @@ static PlacePageRoadType convertRoadType(RoadWarningMarkType roadType) { std::vector m_rawTypes; } +@property(nonatomic, readwrite) PlacePagePreviewData *previewData; +@property(nonatomic, readwrite) CLLocationCoordinate2D locationCoordinate; + @end @implementation PlacePageData @@ -67,7 +70,10 @@ static PlacePageRoadType convertRoadType(RoadWarningMarkType roadType) { if (rawData().IsTrack()) { _objectType = PlacePageObjectTypeTrack; auto const & track = GetFramework().GetBookmarkManager().GetTrack(rawData().GetTrackId()); - _trackData = [[PlacePageTrackData alloc] initWithTrack:*track]; + __weak auto weakSelf = self; + _trackData = [[PlacePageTrackData alloc] initWithTrack:*track onActivePointChanged:^(void) { + [weakSelf handleActiveTrackSelectionPointChanged]; + }]; _isPreviewPlus = track->HasAltitudes(); } _previewData = [[PlacePagePreviewData alloc] initWithRawData:rawData()]; @@ -91,7 +97,12 @@ static PlacePageRoadType convertRoadType(RoadWarningMarkType roadType) { _objectType = PlacePageObjectTypeTrackRecording; _roadType = PlacePageRoadTypeNone; _previewData = [[PlacePagePreviewData alloc] initWithTrackInfo:trackInfo]; - _trackData = [[PlacePageTrackData alloc] initWithTrackInfo:trackInfo elevationInfo:elevationInfo]; + __weak auto weakSelf = self; + _trackData = [[PlacePageTrackData alloc] initWithTrackInfo:trackInfo + elevationInfo:elevationInfo + onActivePointChanged:^(void) { + [weakSelf handleActiveTrackSelectionPointChanged]; + }]; } return self; } @@ -104,6 +115,15 @@ static PlacePageRoadType convertRoadType(RoadWarningMarkType roadType) { self.onTrackRecordingProgressUpdate(); } +- (void)handleActiveTrackSelectionPointChanged { + if (!self || !rawData().IsTrack()) + return; + auto const & trackInfo = GetFramework().GetBookmarkManager().GetTrackSelectionInfo(rawData().GetTrackId()); + auto latlon = mercator::ToLatLon(trackInfo.m_trackPoint); + _locationCoordinate = CLLocationCoordinate2DMake(latlon.m_lat, latlon.m_lon); + self.previewData = [[PlacePagePreviewData alloc] initWithRawData:rawData()]; +} + - (void)dealloc { if (self.mapNodeAttributes != nil) { [[MWMStorage sharedStorage] removeObserver:self]; diff --git a/iphone/Maps/UI/PlacePage/Components/ElevationProfile/ElevationProfileBuilder.swift b/iphone/Maps/UI/PlacePage/Components/ElevationProfile/ElevationProfileBuilder.swift index 8e9e16641..31303c00e 100644 --- a/iphone/Maps/UI/PlacePage/Components/ElevationProfile/ElevationProfileBuilder.swift +++ b/iphone/Maps/UI/PlacePage/Components/ElevationProfile/ElevationProfileBuilder.swift @@ -1,13 +1,11 @@ import CoreApi class ElevationProfileBuilder { - static func build(trackInfo: TrackInfo, - elevationProfileData: ElevationProfileData?, + static func build(trackData: PlacePageTrackData, delegate: ElevationProfileViewControllerDelegate?) -> ElevationProfileViewController { let viewController = ElevationProfileViewController(); let presenter = ElevationProfilePresenter(view: viewController, - trackInfo: trackInfo, - profileData: elevationProfileData, + trackData: trackData, delegate: delegate) viewController.presenter = presenter return viewController diff --git a/iphone/Maps/UI/PlacePage/Components/ElevationProfile/ElevationProfilePresenter.swift b/iphone/Maps/UI/PlacePage/Components/ElevationProfile/ElevationProfilePresenter.swift index 568f7c6df..2fcc31da6 100644 --- a/iphone/Maps/UI/PlacePage/Components/ElevationProfile/ElevationProfilePresenter.swift +++ b/iphone/Maps/UI/PlacePage/Components/ElevationProfile/ElevationProfilePresenter.swift @@ -1,10 +1,14 @@ import Chart import CoreApi -protocol ElevationProfilePresenterProtocol: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { - func configure() - func update(trackInfo: TrackInfo, profileData: ElevationProfileData?) +protocol TrackActivePointPresenter: AnyObject { + func updateActivePoint(_ distance: Double) + func updateMyPosition(_ distance: Double) +} +protocol ElevationProfilePresenterProtocol: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, TrackActivePointPresenter { + func configure() + func update(with trackData: PlacePageTrackData) func onDifficultyButtonPressed() func onSelectedPointChanged(_ point: CGFloat) } @@ -22,8 +26,7 @@ fileprivate struct DescriptionsViewModel { final class ElevationProfilePresenter: NSObject { private weak var view: ElevationProfileViewProtocol? - private var trackInfo: TrackInfo - private var profileData: ElevationProfileData? + private var trackData: PlacePageTrackData private let delegate: ElevationProfileViewControllerDelegate? private let bookmarkManager: BookmarksManager = .shared() @@ -33,19 +36,17 @@ final class ElevationProfilePresenter: NSObject { private let formatter: ElevationProfileFormatter init(view: ElevationProfileViewProtocol, - trackInfo: TrackInfo, - profileData: ElevationProfileData?, + trackData: PlacePageTrackData, formatter: ElevationProfileFormatter = ElevationProfileFormatter(), delegate: ElevationProfileViewControllerDelegate?) { self.view = view self.delegate = delegate self.formatter = formatter - self.trackInfo = trackInfo - self.profileData = profileData - if let profileData { + self.trackData = trackData + if let profileData = trackData.elevationProfileData { self.chartData = ElevationProfileChartData(profileData) } - self.descriptionModels = Self.descriptionModels(for: trackInfo) + self.descriptionModels = Self.descriptionModels(for: trackData.trackInfo) } private static func descriptionModels(for trackInfo: TrackInfo) -> [DescriptionsViewModel] { @@ -56,30 +57,37 @@ final class ElevationProfilePresenter: NSObject { DescriptionsViewModel(title: L("elevation_profile_min_elevation"), value: trackInfo.minElevation, imageName: "ic_em_min_attitude_24") ] } - - deinit { - bookmarkManager.resetElevationActivePointChanged() - bookmarkManager.resetElevationMyPositionChanged() - } } extension ElevationProfilePresenter: ElevationProfilePresenterProtocol { - func update(trackInfo: TrackInfo, profileData: ElevationProfileData?) { - self.profileData = profileData - if let profileData { + func update(with trackData: PlacePageTrackData) { + self.trackData = trackData + if let profileData = trackData.elevationProfileData { self.chartData = ElevationProfileChartData(profileData) } else { self.chartData = nil } - descriptionModels = Self.descriptionModels(for: trackInfo) + descriptionModels = Self.descriptionModels(for: trackData.trackInfo) configure() } + func updateActivePoint(_ distance: Double) { + guard let view, !view.isChartViewInfoHidden else { return } + view.setActivePoint(distance) + } + + func updateMyPosition(_ distance: Double) { + guard let view, !view.isChartViewInfoHidden else { return } + view.setMyPosition(distance) + } + func configure() { view?.isChartViewHidden = false let kMinPointsToDraw = 3 - guard let profileData, let chartData, chartData.points.count >= kMinPointsToDraw else { + guard let profileData = trackData.elevationProfileData, + let chartData, + chartData.points.count >= kMinPointsToDraw else { view?.userInteractionEnabled = false return } @@ -93,14 +101,8 @@ extension ElevationProfilePresenter: ElevationProfilePresenterProtocol { return } - view?.setActivePoint(profileData.activePoint) - view?.setMyPosition(profileData.myPosition) - bookmarkManager.setElevationActivePointChanged(profileData.trackId) { [weak self] distance in - self?.view?.setActivePoint(distance) - } - bookmarkManager.setElevationMyPositionChanged(profileData.trackId) { [weak self] distance in - self?.view?.setMyPosition(distance) - } + view?.setActivePoint(trackData.activePoint) + view?.setMyPosition(trackData.myPosition) } func onDifficultyButtonPressed() { diff --git a/iphone/Maps/UI/PlacePage/PlacePageBuilder.swift b/iphone/Maps/UI/PlacePage/PlacePageBuilder.swift index 8502a0d49..e1aafc01a 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageBuilder.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageBuilder.swift @@ -13,7 +13,9 @@ case .POI, .bookmark: layout = PlacePageCommonLayout(interactor: interactor, storyboard: storyboard, data: data) case .track: - layout = PlacePageTrackLayout(interactor: interactor, storyboard: storyboard, data: data) + let trackLayout = PlacePageTrackLayout(interactor: interactor, storyboard: storyboard, data: data) + interactor.trackActivePointPresenter = trackLayout.elevationMapViewController?.presenter + layout = trackLayout case .trackRecording: layout = PlacePageTrackRecordingLayout(interactor: interactor, storyboard: storyboard, data: data) @unknown default: @@ -38,7 +40,9 @@ case .POI, .bookmark: layout = PlacePageCommonLayout(interactor: interactor, storyboard: storyboard, data: data) case .track: - layout = PlacePageTrackLayout(interactor: interactor, storyboard: storyboard, data: data) + let trackLayout = PlacePageTrackLayout(interactor: interactor, storyboard: storyboard, data: data) + interactor.trackActivePointPresenter = trackLayout.elevationMapViewController?.presenter + layout = trackLayout case .trackRecording: layout = PlacePageTrackRecordingLayout(interactor: interactor, storyboard: storyboard, data: data) @unknown default: diff --git a/iphone/Maps/UI/PlacePage/PlacePageInteractor.swift b/iphone/Maps/UI/PlacePage/PlacePageInteractor.swift index c6788666f..65d4bb4f1 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageInteractor.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageInteractor.swift @@ -7,6 +7,8 @@ class PlacePageInteractor: NSObject { var presenter: PlacePagePresenterProtocol? weak var viewController: UIViewController? weak var mapViewController: MapViewController? + weak var trackActivePointPresenter: TrackActivePointPresenter? + private let bookmarksManager = BookmarksManager.shared() private var placePageData: PlacePageData private var viewWillAppearIsCalledForTheFirstTime = false @@ -17,10 +19,12 @@ class PlacePageInteractor: NSObject { self.mapViewController = mapViewController super.init() addToBookmarksManagerObserverList() + subscribeOnTrackActivePointUpdates() } deinit { removeFromBookmarksManagerObserverList() + unsubscribeFromTrackActivePointUpdates() } private func updatePlacePageIfNeeded() { @@ -49,6 +53,23 @@ class PlacePageInteractor: NSObject { } } + private func subscribeOnTrackActivePointUpdates() { + guard placePageData.objectType == .track, let trackData = placePageData.trackData else { return } + bookmarksManager.setElevationActivePointChanged(trackData.trackId) { [weak self] distance in + self?.trackActivePointPresenter?.updateActivePoint(distance) + trackData.updateActivePointDistance(distance) + } + bookmarksManager.setElevationMyPositionChanged(trackData.trackId) { [weak self] distance in + self?.trackActivePointPresenter?.updateMyPosition(distance) + } + } + + private func unsubscribeFromTrackActivePointUpdates() { + guard placePageData.objectType == .track, let trackData = placePageData.trackData else { return } + bookmarksManager.resetElevationActivePointChanged() + bookmarksManager.resetElevationMyPositionChanged() + } + private func addToBookmarksManagerObserverList() { bookmarksManager.add(self) } @@ -321,7 +342,8 @@ extension PlacePageInteractor: ElevationProfileViewControllerDelegate { func updateMapPoint(_ point: CLLocationCoordinate2D, distance: Double) { guard let trackData = placePageData.trackData, trackData.elevationProfileData?.isTrackRecording == false else { return } - BookmarksManager.shared().setElevationActivePoint(point, distance: distance, trackId: trackData.trackId) + bookmarksManager.setElevationActivePoint(point, distance: distance, trackId: trackData.trackId) + placePageData.trackData?.updateActivePointDistance(distance) } } diff --git a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageTrackLayout.swift b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageTrackLayout.swift index f93d9e800..3de16f824 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageTrackLayout.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageTrackLayout.swift @@ -43,13 +43,10 @@ class PlacePageTrackLayout: IPlacePageLayout { }() lazy var elevationMapViewController: ElevationProfileViewController? = { - guard trackData.trackInfo.hasElevationInfo, - let elevationProfileData = trackData.elevationProfileData else { + guard trackData.trackInfo.hasElevationInfo, trackData.elevationProfileData != nil else { return nil } - return ElevationProfileBuilder.build(trackInfo: trackData.trackInfo, - elevationProfileData: elevationProfileData, - delegate: interactor) + return ElevationProfileBuilder.build(trackData: trackData, delegate: interactor) }() lazy var actionBarViewController: ActionBarViewController = { diff --git a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageTrackRecordingLayout.swift b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageTrackRecordingLayout.swift index bbb458426..57bd63620 100644 --- a/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageTrackRecordingLayout.swift +++ b/iphone/Maps/UI/PlacePage/PlacePageLayout/Layouts/PlacePageTrackRecordingLayout.swift @@ -39,8 +39,7 @@ final class PlacePageTrackRecordingLayout: IPlacePageLayout { guard let trackData = placePageData.trackData else { return nil } - return ElevationProfileBuilder.build(trackInfo: trackData.trackInfo, - elevationProfileData: trackData.elevationProfileData, + return ElevationProfileBuilder.build(trackData: trackData, delegate: interactor) }() @@ -86,9 +85,9 @@ final class PlacePageTrackRecordingLayout: IPlacePageLayout { private extension PlacePageTrackRecordingLayout { func updateTrackRecordingRelatedSections() { - guard let elevationProfileViewController, let trackInfo = placePageData.trackData?.trackInfo else { return } + guard let elevationProfileViewController, let trackData = placePageData.trackData else { return } headerViewController.setTitle(placePageData.previewData.title, secondaryTitle: nil) - elevationProfileViewController.presenter?.update(trackInfo: trackInfo, profileData: placePageData.trackData?.elevationProfileData) + elevationProfileViewController.presenter?.update(with: trackData) presenter?.layoutIfNeeded() } }