mirror of
https://codeberg.org/comaps/comaps
synced 2026-01-06 04:24:29 +00:00
[ios] implement TrackRecording place page
1. add an new screen (layout) 2. add TR icon for the bottom tabbar 3. share current location from the TR PP 4. refactor TR manager to properly handle state updates and pass them to the LiveActivityManager and PlacePage 5. add init/update with TrackInfo/EleInfo methods to the PlacePageData and PlacePagePreviewData to update the PP state Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
This commit is contained in:
committed by
Yannik Bloscheck
parent
5d0b8f1c04
commit
b79724f248
@@ -10,7 +10,7 @@ final class TrackRecordingButtonArea: AvailableArea {
|
||||
}
|
||||
|
||||
override func notifyObserver() {
|
||||
TrackRecordingViewController.updateAvailableArea(areaFrame)
|
||||
TrackRecordingButtonViewController.updateAvailableArea(areaFrame)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,12 +66,9 @@ extension BottomMenuInteractor: BottomMenuInteractorProtocol {
|
||||
}
|
||||
|
||||
func shareLocation(cell: BottomMenuItemCell) {
|
||||
let lastLocation = LocationManager.lastLocation()
|
||||
guard let coordinates = lastLocation?.coordinate else {
|
||||
let alert = UIAlertController(title: L("unknown_current_position"), message: nil, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: L("ok"), style: .default, handler: nil))
|
||||
viewController?.present(alert, animated: true, completion: nil)
|
||||
return;
|
||||
guard let coordinates = LocationManager.lastLocation()?.coordinate else {
|
||||
viewController?.present(UIAlertController.unknownCurrentPosition(), animated: true, completion: nil)
|
||||
return
|
||||
}
|
||||
guard let viewController = viewController else { return }
|
||||
let vc = ActivityViewController.share(forMyPosition: coordinates)
|
||||
@@ -79,8 +76,13 @@ extension BottomMenuInteractor: BottomMenuInteractorProtocol {
|
||||
}
|
||||
|
||||
func toggleTrackRecording() {
|
||||
trackRecorder.processAction(trackRecorder.recordingState == .active ? .stop : .start) { [weak self] in
|
||||
self?.close()
|
||||
switch trackRecorder.recordingState {
|
||||
case .active:
|
||||
break
|
||||
case .inactive:
|
||||
trackRecorder.processAction(.start)
|
||||
}
|
||||
close()
|
||||
MapViewController.shared()?.showTrackRecordingPlacePage()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,19 +62,27 @@ final class ActionBarViewController: UIViewController {
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
var buttons: [ActionBarButtonType] = []
|
||||
if isRoutePlanning {
|
||||
buttons.append(.routeFrom)
|
||||
}
|
||||
let hasAnyPhones = !(placePageData.infoData?.phones ?? []).isEmpty
|
||||
if hasAnyPhones, AppInfo.shared().canMakeCalls {
|
||||
buttons.append(.call)
|
||||
}
|
||||
if !isRoutePlanning {
|
||||
buttons.append(.routeFrom)
|
||||
switch placePageData.objectType {
|
||||
case .POI, .bookmark, .track:
|
||||
if isRoutePlanning {
|
||||
buttons.append(.routeFrom)
|
||||
}
|
||||
let hasAnyPhones = !(placePageData.infoData?.phones ?? []).isEmpty
|
||||
if hasAnyPhones, AppInfo.shared().canMakeCalls {
|
||||
buttons.append(.call)
|
||||
}
|
||||
if !isRoutePlanning {
|
||||
buttons.append(.routeFrom)
|
||||
}
|
||||
case .trackRecording:
|
||||
break
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
|
||||
assert(buttons.count > 0)
|
||||
guard !buttons.isEmpty else { return }
|
||||
visibleButtons.append(buttons[0])
|
||||
if buttons.count > 1 {
|
||||
additionalButtons.append(contentsOf: buttons.suffix(from: 1))
|
||||
@@ -83,21 +91,24 @@ final class ActionBarViewController: UIViewController {
|
||||
|
||||
private func configButton2() {
|
||||
var buttons: [ActionBarButtonType] = []
|
||||
if canAddStop {
|
||||
buttons.append(.routeAddStop)
|
||||
}
|
||||
switch placePageData.objectType {
|
||||
case .POI, .bookmark:
|
||||
if canAddStop {
|
||||
buttons.append(.routeAddStop)
|
||||
}
|
||||
buttons.append(.bookmark)
|
||||
case .track:
|
||||
if canAddStop {
|
||||
buttons.append(.routeAddStop)
|
||||
}
|
||||
buttons.append(.track)
|
||||
case .trackRecording:
|
||||
// TODO: implement for track recording
|
||||
break
|
||||
buttons.append(.saveTrackRecording)
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
assert(buttons.count > 0)
|
||||
|
||||
visibleButtons.append(buttons[0])
|
||||
if buttons.count > 1 {
|
||||
additionalButtons.append(contentsOf: buttons.suffix(from: 1))
|
||||
@@ -105,7 +116,14 @@ final class ActionBarViewController: UIViewController {
|
||||
}
|
||||
|
||||
private func configButton3() {
|
||||
visibleButtons.append(.routeTo)
|
||||
switch placePageData.objectType {
|
||||
case .POI, .bookmark, .track:
|
||||
visibleButtons.append(.routeTo)
|
||||
case .trackRecording:
|
||||
break
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
}
|
||||
|
||||
private func configButton4() {
|
||||
|
||||
@@ -85,6 +85,11 @@ extension ElevationProfilePresenter: ElevationProfilePresenterProtocol {
|
||||
view?.setChartData(ChartPresentationData(chartData, formatter: formatter))
|
||||
view?.reloadDescription()
|
||||
|
||||
guard !profileData.isTrackRecording else {
|
||||
view?.isChartViewInfoHidden = true
|
||||
return
|
||||
}
|
||||
|
||||
view?.setActivePoint(profileData.activePoint)
|
||||
view?.setMyPosition(profileData.myPosition)
|
||||
bookmarkManager.setElevationActivePointChanged(profileData.trackId) { [weak self] distance in
|
||||
|
||||
@@ -51,8 +51,6 @@ extension PlacePageHeaderPresenter: PlacePageHeaderPresenterProtocol {
|
||||
view?.isExpandViewHidden = true
|
||||
view?.isShadowViewHidden = false
|
||||
}
|
||||
// TODO: (KK) Enable share button for the tracks to share the whole track gpx/kml
|
||||
view?.isShareButtonHidden = false
|
||||
}
|
||||
|
||||
func onClosePress() {
|
||||
|
||||
@@ -2,7 +2,6 @@ protocol PlacePageHeaderViewProtocol: AnyObject {
|
||||
var presenter: PlacePageHeaderPresenterProtocol? { get set }
|
||||
var isExpandViewHidden: Bool { get set }
|
||||
var isShadowViewHidden: Bool { get set }
|
||||
var isShareButtonHidden: Bool { get set }
|
||||
|
||||
func setTitle(_ title: String?, secondaryTitle: String?)
|
||||
func showShareTrackMenu()
|
||||
@@ -78,15 +77,6 @@ extension PlacePageHeaderViewController: PlacePageHeaderViewProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
var isShareButtonHidden: Bool {
|
||||
get {
|
||||
shareButton.isHidden
|
||||
}
|
||||
set {
|
||||
shareButton.isHidden = newValue
|
||||
}
|
||||
}
|
||||
|
||||
func setTitle(_ title: String?, secondaryTitle: String?) {
|
||||
titleText = title
|
||||
secondaryText = secondaryTitle
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
case .track:
|
||||
layout = PlacePageTrackLayout(interactor: interactor, storyboard: storyboard, data: data)
|
||||
case .trackRecording:
|
||||
// TODO: Implement PlacePageTrackRecordingLayout
|
||||
fatalError("PlacePageTrackRecordingLayout is not implemented")
|
||||
layout = PlacePageTrackRecordingLayout(interactor: interactor, storyboard: storyboard, data: data)
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
@@ -34,14 +33,14 @@
|
||||
data: data,
|
||||
mapViewController: MapViewController.shared()!)
|
||||
let layout: IPlacePageLayout
|
||||
let storyboard = viewController.storyboard!
|
||||
switch data.objectType {
|
||||
case .POI, .bookmark:
|
||||
layout = PlacePageCommonLayout(interactor: interactor, storyboard: viewController.storyboard!, data: data)
|
||||
layout = PlacePageCommonLayout(interactor: interactor, storyboard: storyboard, data: data)
|
||||
case .track:
|
||||
layout = PlacePageTrackLayout(interactor: interactor, storyboard: viewController.storyboard!, data: data)
|
||||
layout = PlacePageTrackLayout(interactor: interactor, storyboard: storyboard, data: data)
|
||||
case .trackRecording:
|
||||
// TODO: Implement PlacePageTrackRecordingLayout
|
||||
fatalError("PlacePageTrackRecordingLayout is not implemented")
|
||||
layout = PlacePageTrackRecordingLayout(interactor: interactor, storyboard: storyboard, data: data)
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
|
||||
@@ -246,9 +246,19 @@ extension PlacePageInteractor: ActionBarViewControllerDelegate {
|
||||
fatalError("More button should've been handled in ActionBarViewContoller")
|
||||
case .track:
|
||||
guard placePageData.trackData != nil else { return }
|
||||
// TODO: This is temporary solution. Remove the dialog and use the MWMPlacePageManagerHelper.removeTrack
|
||||
// TODO: (KK) This is temporary solution. Remove the dialog and use the MWMPlacePageManagerHelper.removeTrack
|
||||
// directly here when the track recovery mechanism will be implemented.
|
||||
showTrackDeletionConfirmationDialog()
|
||||
case .saveTrackRecording:
|
||||
// TODO: (KK) pass name typed by user
|
||||
TrackRecordingManager.shared.processAction(.stopAndSave(name: "")) { [weak self] result in
|
||||
switch result {
|
||||
case .success:
|
||||
break
|
||||
case .error:
|
||||
self?.presenter?.closeAnimated()
|
||||
}
|
||||
}
|
||||
@unknown default:
|
||||
fatalError()
|
||||
}
|
||||
@@ -298,8 +308,8 @@ extension PlacePageInteractor: ElevationProfileViewControllerDelegate {
|
||||
}
|
||||
|
||||
func updateMapPoint(_ point: CLLocationCoordinate2D, distance: Double) {
|
||||
guard let trackId = placePageData.trackData?.trackId else { return }
|
||||
BookmarksManager.shared().setElevationActivePoint(point, distance: distance, trackId: trackId)
|
||||
guard let trackData = placePageData.trackData, trackData.elevationProfileData?.isTrackRecording == false else { return }
|
||||
BookmarksManager.shared().setElevationActivePoint(point, distance: distance, trackId: trackData.trackId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,7 +333,12 @@ extension PlacePageInteractor: PlacePageHeaderViewControllerDelegate {
|
||||
case .track:
|
||||
presenter?.showShareTrackMenu()
|
||||
default:
|
||||
fatalError()
|
||||
guard let coordinates = LocationManager.lastLocation()?.coordinate else {
|
||||
viewController?.present(UIAlertController.unknownCurrentPosition(), animated: true, completion: nil)
|
||||
return
|
||||
}
|
||||
let activity = ActivityViewController.share(forMyPosition: coordinates)
|
||||
activity.present(inParentViewController: mapViewController, anchorView: sourceView)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ typedef NS_ENUM(NSInteger, MWMActionBarButtonType) {
|
||||
MWMActionBarButtonTypeBookingSearch,
|
||||
MWMActionBarButtonTypeBookmark,
|
||||
MWMActionBarButtonTypeTrack,
|
||||
MWMActionBarButtonTypeSaveTrackRecording,
|
||||
MWMActionBarButtonTypeCall,
|
||||
MWMActionBarButtonTypeDownload,
|
||||
MWMActionBarButtonTypeMore,
|
||||
|
||||
@@ -19,6 +19,8 @@ NSString *titleForButton(MWMActionBarButtonType type, BOOL isSelected) {
|
||||
case MWMActionBarButtonTypeBookmark:
|
||||
case MWMActionBarButtonTypeTrack:
|
||||
return L(isSelected ? @"delete" : @"save");
|
||||
case MWMActionBarButtonTypeSaveTrackRecording:
|
||||
return L(@"save");
|
||||
case MWMActionBarButtonTypeRouteFrom:
|
||||
return L(@"p2p_from_here");
|
||||
case MWMActionBarButtonTypeRouteTo:
|
||||
@@ -55,7 +57,8 @@ NSString *titleForButton(MWMActionBarButtonType type, BOOL isSelected) {
|
||||
self.label.text = titleForButton(self.type, isSelected);
|
||||
self.extraBackground.hidden = YES;
|
||||
self.button.coloring = MWMButtonColoringBlack;
|
||||
|
||||
[self.button.imageView setContentMode:UIViewContentModeScaleAspectFit];
|
||||
|
||||
switch (self.type) {
|
||||
case MWMActionBarButtonTypeDownload: {
|
||||
if (self.mapDownloadProgress)
|
||||
@@ -108,6 +111,9 @@ NSString *titleForButton(MWMActionBarButtonType type, BOOL isSelected) {
|
||||
[self.button setImage:[[UIImage imageNamed:@"ic_route_manager_trash"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal];
|
||||
self.button.coloring = MWMButtonColoringRed;
|
||||
break;
|
||||
case MWMActionBarButtonTypeSaveTrackRecording:
|
||||
[self.button setImage:[UIImage imageNamed:@"ic_placepage_save_track_recording"] forState:UIControlStateNormal];
|
||||
break;
|
||||
case MWMActionBarButtonTypeRouteFrom:
|
||||
[self.button setImage:[UIImage imageNamed:@"ic_route_from"] forState:UIControlStateNormal];
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
final class PlacePageTrackRecordingLayout: IPlacePageLayout {
|
||||
private var placePageData: PlacePageData
|
||||
private var interactor: PlacePageInteractor
|
||||
private let storyboard: UIStoryboard
|
||||
weak var presenter: PlacePagePresenterProtocol?
|
||||
|
||||
lazy var bodyViewControllers: [UIViewController] = {
|
||||
return configureViewControllers()
|
||||
}()
|
||||
|
||||
var actionBar: ActionBarViewController? {
|
||||
actionBarViewController
|
||||
}
|
||||
|
||||
var navigationBar: UIViewController? {
|
||||
placePageNavigationViewController
|
||||
}
|
||||
|
||||
lazy var headerViewControllers: [UIViewController] = {
|
||||
[headerViewController]
|
||||
}()
|
||||
|
||||
lazy var headerViewController: PlacePageHeaderViewController = {
|
||||
return PlacePageHeaderBuilder.build(data: placePageData, delegate: interactor, headerType: .flexible)
|
||||
}()
|
||||
|
||||
lazy var placePageNavigationViewController: PlacePageHeaderViewController = {
|
||||
return PlacePageHeaderBuilder.build(data: placePageData, delegate: interactor, headerType: .fixed)
|
||||
}()
|
||||
|
||||
lazy var editTrackViewController: PlacePageEditBookmarkOrTrackViewController = {
|
||||
let vc = storyboard.instantiateViewController(ofType: PlacePageEditBookmarkOrTrackViewController.self)
|
||||
vc.view.isHidden = true
|
||||
vc.delegate = interactor
|
||||
return vc
|
||||
}()
|
||||
|
||||
lazy var elevationProfileViewController: ElevationProfileViewController? = {
|
||||
guard let trackData = placePageData.trackData else {
|
||||
return nil
|
||||
}
|
||||
return ElevationProfileBuilder.build(trackInfo: trackData.trackInfo,
|
||||
elevationProfileData: trackData.elevationProfileData,
|
||||
delegate: interactor)
|
||||
}()
|
||||
|
||||
lazy var actionBarViewController: ActionBarViewController = {
|
||||
let vc = storyboard.instantiateViewController(ofType: ActionBarViewController.self)
|
||||
vc.placePageData = placePageData
|
||||
vc.canAddStop = MWMRouter.canAddIntermediatePoint()
|
||||
vc.isRoutePlanning = MWMNavigationDashboardManager.shared().state != .hidden
|
||||
vc.delegate = interactor
|
||||
return vc
|
||||
}()
|
||||
|
||||
init(interactor: PlacePageInteractor, storyboard: UIStoryboard, data: PlacePageData) {
|
||||
self.interactor = interactor
|
||||
self.storyboard = storyboard
|
||||
self.placePageData = data
|
||||
}
|
||||
|
||||
private func configureViewControllers() -> [UIViewController] {
|
||||
var viewControllers = [UIViewController]()
|
||||
|
||||
if let elevationProfileViewController {
|
||||
viewControllers.append(elevationProfileViewController)
|
||||
}
|
||||
|
||||
placePageData.onTrackRecordingProgressUpdate = { [weak self] in
|
||||
self?.updateTrackRecordingRelatedSections()
|
||||
}
|
||||
|
||||
return viewControllers
|
||||
}
|
||||
|
||||
func calculateSteps(inScrollView scrollView: UIScrollView, compact: Bool) -> [PlacePageState] {
|
||||
var steps: [PlacePageState] = []
|
||||
let scrollHeight = scrollView.height
|
||||
steps.append(.closed(-scrollHeight))
|
||||
steps.append(.full(0))
|
||||
return steps
|
||||
}
|
||||
}
|
||||
|
||||
private extension PlacePageTrackRecordingLayout {
|
||||
func updateTrackRecordingRelatedSections() {
|
||||
guard let elevationProfileViewController, let trackInfo = placePageData.trackData?.trackInfo else { return }
|
||||
headerViewController.setTitle(placePageData.previewData.title, secondaryTitle: nil)
|
||||
elevationProfileViewController.presenter?.update(trackInfo: trackInfo, profileData: placePageData.trackData?.elevationProfileData)
|
||||
presenter?.layoutIfNeeded()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user