[ios] refactor PP dependencies to support UDF

View -> Interactor -> Presenter -> View

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
This commit is contained in:
Kiryl Kaveryn 2024-11-05 16:24:34 +04:00 committed by Roman Tsisyk
parent 8efd7d30ac
commit d2310433d6
5 changed files with 100 additions and 94 deletions

View file

@ -74,7 +74,6 @@ class InfoItemViewController: UIViewController {
protocol PlacePageInfoViewControllerDelegate: AnyObject {
var shouldShowOpenInApp: Bool { get }
func viewWillAppear()
func didPressCall()
func didPressWebsite()
func didPressWebsiteMenu()
@ -144,11 +143,6 @@ class PlacePageInfoViewController: UIViewController {
setupViews()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
delegate?.viewWillAppear()
}
// MARK: private
private func setupViews() {
if let openingHours = placePageInfoData.openingHours {

View file

@ -9,16 +9,15 @@
let interactor = PlacePageInteractor(viewController: viewController,
data: data,
mapViewController: MapViewController.shared()!)
let layout:IPlacePageLayout
if data.elevationProfileData != nil {
let layout: IPlacePageLayout
if data.isTrack {
layout = PlacePageElevationLayout(interactor: interactor, storyboard: storyboard, data: data)
} else {
layout = PlacePageCommonLayout(interactor: interactor, storyboard: storyboard, data: data)
}
let presenter = PlacePagePresenter(view: viewController, interactor: interactor)
let presenter = PlacePagePresenter(view: viewController)
viewController.setLayout(layout)
viewController.presenter = presenter
viewController.interactor = interactor
interactor.presenter = presenter
layout.presenter = presenter
return viewController
@ -30,15 +29,14 @@
let interactor = PlacePageInteractor(viewController: viewController,
data: data,
mapViewController: MapViewController.shared()!)
let layout:IPlacePageLayout
if data.elevationProfileData != nil {
let layout: IPlacePageLayout
if data.isTrack {
layout = PlacePageElevationLayout(interactor: interactor, storyboard: viewController.storyboard!, data: data)
} else {
layout = PlacePageCommonLayout(interactor: interactor, storyboard: viewController.storyboard!, data: data)
}
let presenter = PlacePagePresenter(view: viewController, interactor: interactor)
viewController.presenter = presenter
let presenter = PlacePagePresenter(view: viewController)
viewController.interactor = interactor
interactor.presenter = presenter
layout.presenter = presenter
viewController.updateWithLayout(layout)

View file

@ -1,9 +1,10 @@
protocol PlacePageInteractorProtocol: AnyObject {
func viewWillAppear()
func updateTopBound(_ bound: CGFloat, duration: TimeInterval)
}
class PlacePageInteractor: NSObject {
weak var presenter: PlacePagePresenterProtocol?
var presenter: PlacePagePresenterProtocol?
weak var viewController: UIViewController?
weak var mapViewController: MapViewController?
private let bookmarksManager = BookmarksManager.shared()
@ -23,13 +24,18 @@ class PlacePageInteractor: NSObject {
}
private func updateBookmarkIfNeeded() {
guard let bookmarkId = placePageData.bookmarkData?.bookmarkId else { return }
guard bookmarksManager.hasBookmark(bookmarkId) else {
presenter?.closeAnimated()
return
if placePageData.isTrack {
guard let trackId = placePageData.trackData?.trackId, bookmarksManager.hasTrack(trackId) else {
presenter?.closeAnimated()
return
}
} else {
guard let bookmarkId = placePageData.bookmarkData?.bookmarkId, bookmarksManager.hasBookmark(bookmarkId) else {
return
}
FrameworkHelper.updatePlacePageData()
placePageData.updateBookmarkStatus()
}
FrameworkHelper.updatePlacePageData()
placePageData.updateBookmarkStatus()
}
private func addToBookmarksManagerObserverList() {
@ -42,6 +48,15 @@ class PlacePageInteractor: NSObject {
}
extension PlacePageInteractor: PlacePageInteractorProtocol {
func viewWillAppear() {
// Skip data reloading on the first appearance, to avoid unnecessary updates.
guard viewWillAppearIsCalledForTheFirstTime else {
viewWillAppearIsCalledForTheFirstTime = true
return
}
updateBookmarkIfNeeded()
}
func updateTopBound(_ bound: CGFloat, duration: TimeInterval) {
mapViewController?.setPlacePageTopBound(bound, duration: duration)
}
@ -53,14 +68,7 @@ extension PlacePageInteractor: PlacePageInfoViewControllerDelegate {
var shouldShowOpenInApp: Bool {
!OpenInApplication.availableApps.isEmpty
}
func viewWillAppear() {
// Skip data reloading on the first appearance, to avoid unnecessary updates.
guard viewWillAppearIsCalledForTheFirstTime else { return }
viewWillAppearIsCalledForTheFirstTime = true
updateBookmarkIfNeeded()
}
func didPressCall() {
MWMPlacePageManagerHelper.call(placePageData)
}
@ -177,6 +185,10 @@ extension PlacePageInteractor: PlacePageBookmarkViewControllerDelegate {
func bookmarkDidPressEdit() {
MWMPlacePageManagerHelper.editBookmark(placePageData)
}
func trackDidPressEdit() {
MWMPlacePageManagerHelper.editTrack(placePageData)
}
}
// MARK: - ActionBarViewControllerDelegate
@ -228,6 +240,10 @@ extension PlacePageInteractor: ActionBarViewControllerDelegate {
MWMPlacePageManagerHelper.avoidFerry()
case .more:
fatalError("More button should've been handled in ActionBarViewContoller")
case .track:
guard placePageData.trackData != nil else { return }
MWMPlacePageManagerHelper.removeTrack(placePageData)
presenter?.closeAnimated()
@unknown default:
fatalError()
}
@ -241,8 +257,9 @@ extension PlacePageInteractor: ElevationProfileViewControllerDelegate {
MWMPlacePageManagerHelper.openElevationDifficultPopup(placePageData)
}
func updateMapPoint(_ distance: Double) {
BookmarksManager.shared().setElevationActivePoint(distance, trackId: placePageData.elevationProfileData!.trackId)
func updateMapPoint(_ point: CLLocationCoordinate2D, distance: Double) {
guard let trackId = placePageData.trackData?.trackId else { return }
BookmarksManager.shared().setElevationActivePoint(point, distance: distance, trackId: trackId)
}
}

View file

@ -3,18 +3,14 @@ protocol PlacePagePresenterProtocol: AnyObject {
func layoutIfNeeded()
func showNextStop()
func closeAnimated()
func updateTopBound(_ bound: CGFloat, duration: TimeInterval)
func showAlert(_ alert: UIAlertController)
}
class PlacePagePresenter: NSObject {
private weak var view: PlacePageViewProtocol!
private let interactor: PlacePageInteractorProtocol
init(view: PlacePageViewProtocol,
interactor: PlacePageInteractorProtocol) {
init(view: PlacePageViewProtocol) {
self.view = view
self.interactor = interactor
}
}
@ -37,10 +33,6 @@ extension PlacePagePresenter: PlacePagePresenterProtocol {
view.closeAnimated(completion: nil)
}
func updateTopBound(_ bound: CGFloat, duration: TimeInterval) {
interactor.updateTopBound(bound, duration: duration)
}
func showAlert(_ alert: UIAlertController) {
view.showAlert(alert)
}

View file

@ -1,5 +1,5 @@
protocol PlacePageViewProtocol: AnyObject {
var presenter: PlacePagePresenterProtocol! { get set }
var interactor: PlacePageInteractorProtocol! { get set }
func setLayout(_ layout: IPlacePageLayout)
func closeAnimated(completion: (() -> Void)?)
@ -35,7 +35,7 @@ final class PlacePageScrollView: UIScrollView {
stackView.distribution = .fill
return stackView
}()
var presenter: PlacePagePresenterProtocol!
var interactor: PlacePageInteractorProtocol!
var beginDragging = false
var rootViewController: MapViewController {
MapViewController.shared()!
@ -69,6 +69,11 @@ final class PlacePageScrollView: UIScrollView {
previousTraitCollection = traitCollection
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
interactor?.viewWillAppear()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
updatePreviewOffset()
@ -221,6 +226,55 @@ final class PlacePageScrollView: UIScrollView {
return result
}
private func addActionBar(_ actionBarViewController: UIViewController) {
addChild(actionBarViewController)
actionBarViewController.view.translatesAutoresizingMaskIntoConstraints = false
actionBarContainerView.addSubview(actionBarViewController.view)
actionBarViewController.didMove(toParent: self)
NSLayoutConstraint.activate([
actionBarViewController.view.leadingAnchor.constraint(equalTo: actionBarContainerView.leadingAnchor),
actionBarViewController.view.topAnchor.constraint(equalTo: actionBarContainerView.topAnchor),
actionBarViewController.view.trailingAnchor.constraint(equalTo: actionBarContainerView.trailingAnchor),
actionBarViewController.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
])
}
private func addNavigationBar(_ header: UIViewController) {
header.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(header.view)
addChild(header)
NSLayoutConstraint.activate([
header.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
header.view.topAnchor.constraint(equalTo: view.topAnchor),
header.view.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
}
private func scrollTo(_ point: CGPoint, animated: Bool = true, forced: Bool = false, completion: (() -> Void)? = nil) {
if alternativeSizeClass(iPhone: beginDragging, iPad: true) && !forced {
return
}
if forced {
beginDragging = true
}
let scrollPosition = CGPoint(x: point.x, y: min(scrollView.contentSize.height - scrollView.height, point.y))
let bound = view.height + scrollPosition.y
if animated {
updateTopBound(bound, duration: kDefaultAnimationDuration)
UIView.animate(withDuration: kDefaultAnimationDuration, animations: { [weak scrollView] in
scrollView?.contentOffset = scrollPosition
self.layoutIfNeeded()
}) { complete in
if complete {
completion?()
}
}
} else {
scrollView?.contentOffset = scrollPosition
completion?()
}
}
private func showLastStop() {
if let lastStop = scrollSteps.last {
scrollTo(CGPoint(x: 0, y: lastStop.offset), forced: true)
@ -229,7 +283,7 @@ final class PlacePageScrollView: UIScrollView {
private func updateTopBound(_ bound: CGFloat, duration: TimeInterval) {
alternativeSizeClass(iPhone: {
presenter.updateTopBound(bound, duration: duration)
interactor.updateTopBound(bound, duration: duration)
}, iPad: {})
}
}
@ -265,55 +319,6 @@ extension PlacePageViewController: PlacePageViewProtocol {
}
}
func addActionBar(_ actionBarViewController: UIViewController) {
addChild(actionBarViewController)
actionBarViewController.view.translatesAutoresizingMaskIntoConstraints = false
actionBarContainerView.addSubview(actionBarViewController.view)
actionBarViewController.didMove(toParent: self)
NSLayoutConstraint.activate([
actionBarViewController.view.leadingAnchor.constraint(equalTo: actionBarContainerView.leadingAnchor),
actionBarViewController.view.topAnchor.constraint(equalTo: actionBarContainerView.topAnchor),
actionBarViewController.view.trailingAnchor.constraint(equalTo: actionBarContainerView.trailingAnchor),
actionBarViewController.view.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
])
}
func addNavigationBar(_ header: UIViewController) {
header.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(header.view)
addChild(header)
NSLayoutConstraint.activate([
header.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
header.view.topAnchor.constraint(equalTo: view.topAnchor),
header.view.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
}
func scrollTo(_ point: CGPoint, animated: Bool = true, forced: Bool = false, completion: (() -> Void)? = nil) {
if alternativeSizeClass(iPhone: beginDragging, iPad: true) && !forced {
return
}
if forced {
beginDragging = true
}
let scrollPosition = CGPoint(x: point.x, y: min(scrollView.contentSize.height - scrollView.height, point.y))
let bound = view.height + scrollPosition.y
if animated {
updateTopBound(bound, duration: kDefaultAnimationDuration)
UIView.animate(withDuration: kDefaultAnimationDuration, animations: { [weak scrollView] in
scrollView?.contentOffset = scrollPosition
self.layoutIfNeeded()
}) { complete in
if complete {
completion?()
}
}
} else {
scrollView?.contentOffset = scrollPosition
completion?()
}
}
func showNextStop() {
if let nextStop = scrollSteps.last(where: { $0.offset > scrollView.contentOffset.y }) {
scrollTo(CGPoint(x: 0, y: nextStop.offset), forced: true)