Skip to content

Commit

Permalink
Remove "Route Feedback" and replace EORVC storyboard with programmati…
Browse files Browse the repository at this point in the history
…c view

Note this was cherry-picked, and no longer works due to change in maplibre#54
  • Loading branch information
michaelkirk committed Jun 24, 2024
1 parent 7c02808 commit 411a1f2
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 519 deletions.
27 changes: 0 additions & 27 deletions MapboxCoreNavigation/EndOfRouteFeedback.swift

This file was deleted.

6 changes: 0 additions & 6 deletions MapboxNavigation/DayStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ open class DayStyle: Style {
PrimaryLabel.appearance(whenContainedInInstancesOf: [InstructionsBannerView.self]).normalTextColor = #colorLiteral(red: 0.09803921569, green: 0.09803921569, blue: 0.09803921569, alpha: 1)
PrimaryLabel.appearance(whenContainedInInstancesOf: [StepInstructionsView.self]).normalTextColor = #colorLiteral(red: 0.09803921569, green: 0.09803921569, blue: 0.09803921569, alpha: 1)
ProgressBar.appearance().barColor = #colorLiteral(red: 0.149, green: 0.239, blue: 0.341, alpha: 1)
RatingControl.appearance().normalColor = #colorLiteral(red: 0.8508961797, green: 0.8510394692, blue: 0.850877285, alpha: 1)
RatingControl.appearance().selectedColor = #colorLiteral(red: 0.1205472574, green: 0.2422055006, blue: 0.3489340544, alpha: 1)
ReportButton.appearance().backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
ReportButton.appearance().textColor = tintColor!
ReportButton.appearance().textFont = UIFont.systemFont(ofSize: 15, weight: .medium).adjustedFont
Expand Down Expand Up @@ -189,8 +187,6 @@ open class NightStyle: DayStyle {
DistanceLabel.appearance(whenContainedInInstancesOf: [StepInstructionsView.self]).valueTextColor = #colorLiteral(red: 0.9842069745, green: 0.9843751788, blue: 0.9841964841, alpha: 1)
DistanceRemainingLabel.appearance().normalTextColor = #colorLiteral(red: 0.7991961837, green: 0.8232284188, blue: 0.8481693864, alpha: 1)
EndOfRouteButton.appearance().textColor = .white
EndOfRouteCommentView.appearance().backgroundColor = #colorLiteral(red: 0.1875049942, green: 0.2981707989, blue: 0.4181857639, alpha: 1)
EndOfRouteCommentView.appearance().normalTextColor = .white
EndOfRouteContentView.appearance().backgroundColor = backgroundColor
EndOfRouteStaticLabel.appearance().alpha = 1.0
EndOfRouteStaticLabel.appearance().textColor = UIColor.white.withAlphaComponent(0.9)
Expand All @@ -216,8 +212,6 @@ open class NightStyle: DayStyle {
PrimaryLabel.appearance(whenContainedInInstancesOf: [InstructionsBannerView.self]).normalTextColor = #colorLiteral(red: 0.9996390939, green: 1, blue: 0.9997561574, alpha: 1)
PrimaryLabel.appearance(whenContainedInInstancesOf: [StepInstructionsView.self]).normalTextColor = #colorLiteral(red: 0.9996390939, green: 1, blue: 0.9997561574, alpha: 1)
ProgressBar.appearance().barColor = #colorLiteral(red: 0.9842069745, green: 0.9843751788, blue: 0.9841964841, alpha: 1)
RatingControl.appearance().normalColor = #colorLiteral(red: 0.149668334, green: 0.1680230035, blue: 0.1472480238, alpha: 1)
RatingControl.appearance().selectedColor = #colorLiteral(red: 0.9803059896, green: 0.9978019022, blue: 1, alpha: 1)
ReportButton.appearance().backgroundColor = backgroundColor
ReportButton.appearance().textColor = #colorLiteral(red: 0.9842069745, green: 0.9843751788, blue: 0.9841964841, alpha: 1)
ResumeButton.appearance().backgroundColor = backgroundColor
Expand Down
219 changes: 78 additions & 141 deletions MapboxNavigation/EndOfRouteViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,43 +23,60 @@ open class EndOfRouteTitleLabel: StylableLabel {}
@objc(MBEndOfRouteStaticLabel)
open class EndOfRouteStaticLabel: StylableLabel {}

/// :nodoc:
@objc(MBEndOfRouteCommentView)
open class EndOfRouteCommentView: StylableTextView {}

/// :nodoc:
@objc(MBEndOfRouteButton)
open class EndOfRouteButton: StylableButton {}

@objc(MBEndOfRouteViewController)
class EndOfRouteViewController: UIViewController {
// MARK: - IBOutlets

@IBOutlet var labelContainer: UIView!
@IBOutlet var staticYouHaveArrived: EndOfRouteStaticLabel!
@IBOutlet var primary: UILabel!
@IBOutlet var endNavigationButton: UIButton!
@IBOutlet var stars: RatingControl!
@IBOutlet var commentView: UITextView!
@IBOutlet var commentViewContainer: UIView!
@IBOutlet var showCommentView: NSLayoutConstraint!
@IBOutlet var hideCommentView: NSLayoutConstraint!
@IBOutlet var ratingCommentsSpacing: NSLayoutConstraint!

// MARK: - Properties

lazy var placeholder: String = NSLocalizedString("END_OF_ROUTE_TITLE", bundle: .mapboxNavigation, value: "How can we improve?", comment: "Comment Placeholder Text")
lazy var endNavigation: String = NSLocalizedString("END_NAVIGATION", bundle: .mapboxNavigation, value: "End Navigation", comment: "End Navigation Button Text")

typealias DismissHandler = (Int, String?) -> Void
var dismissHandler: DismissHandler?
var comment: String?
var rating: Int = 0 {
didSet {
self.rating == 0 ? self.hideComments() : self.showComments()
}
}

lazy var column: UIStackView = {
let spacerView = UIView()
spacerView.setContentHuggingPriority(.defaultLow, for: .vertical)
spacerView.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
let column = UIStackView(arrangedSubviews: [self.staticYouHaveArrived, self.primaryLabel, spacerView, self.endNavigationButton])
column.axis = .vertical
column.alignment = .center
column.spacing = 8
column.translatesAutoresizingMaskIntoConstraints = false
return column
}()

lazy var staticYouHaveArrived: EndOfRouteStaticLabel = {
let label = EndOfRouteStaticLabel()
label.text = self.endOfRouteArrivedText
return label
}()

lazy var primaryLabel: EndOfRouteTitleLabel = {
let label = EndOfRouteTitleLabel()
label.numberOfLines = 3
label.adjustsFontSizeToFitWidth = true
return label
}()

lazy var endNavigationButton: EndOfRouteButton = {
let button = EndOfRouteButton(type: .system)
button.setTitle(self.endNavigationText, for: .normal)
button.addTarget(self, action: #selector(self.endNavigationPressed(_:)), for: .touchUpInside)
return button
}()

lazy var endOfRouteArrivedText: String = NSLocalizedString("END_OF_ROUTE_ARRIVED", bundle: .mapboxNavigation, value: "You have arrived", comment: "Title used for arrival")
lazy var endNavigationText: String = NSLocalizedString("END_NAVIGATION", bundle: .mapboxNavigation, value: "End Navigation", comment: "End Navigation Button Text")

let dismissHandler: () -> Void
init(dismissHandler: @escaping () -> Void) {
self.dismissHandler = dismissHandler
super.init(nibName: nil, bundle: nil)
}

@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

open var destination: Waypoint? {
didSet {
guard isViewLoaded else { return }
Expand All @@ -69,137 +86,57 @@ class EndOfRouteViewController: UIViewController {

// MARK: - Lifecycle Methods

override func viewDidLoad() {
super.viewDidLoad()
self.clearInterface()
self.stars.didChangeRating = { [weak self] new in self?.rating = new }
self.setPlaceholderText()
self.styleCommentView()
self.commentViewContainer.alpha = 0.0 // setting initial hidden state
override func loadView() {
self.view = EndOfRouteContentView()
self.view.addSubview(self.column)
self.activateLayoutConstraints()
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillDisappear(animated)
view.roundCorners([.topLeft, .topRight])
super.viewWillAppear(animated)
preferredContentSize.height = self.height(for: .normal)
self.updateInterface()
}

// MARK: - IBActions
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// roundCorners needs to be called whenever the bounds change
view.roundCorners([.topLeft, .topRight])
}

@IBAction func endNavigationPressed(_ sender: Any) {
self.dismissView()
// MARK: - Actions

@objc func endNavigationPressed(_ sender: Any) {
self.dismissHandler()
}

// MARK: - Private Functions

private func styleCommentView() {
self.commentView.layer.cornerRadius = 6.0
self.commentView.layer.borderColor = UIColor.lightGray.cgColor
self.commentView.layer.borderWidth = 1.0
self.commentView.textContainerInset = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
}

fileprivate func dismissView() {
let dismissal: () -> Void = { self.dismissHandler?(self.rating, self.comment) }
guard self.commentView.isFirstResponder else { return _ = dismissal() }
self.commentView.resignFirstResponder()
let fireTime = DispatchTime.now() + 0.3 // Not ideal, but works for now
DispatchQueue.main.asyncAfter(deadline: fireTime, execute: dismissal)
}

private func showComments(animated: Bool = true) {
self.showCommentView.isActive = true
self.hideCommentView.isActive = false
self.ratingCommentsSpacing.constant = ConstraintSpacing.closer.rawValue
preferredContentSize.height = self.height(for: .commentShowing)

let animate = {
self.view.layoutIfNeeded()
self.commentViewContainer.alpha = 1.0
self.labelContainer.alpha = 0.0
}

let completion: (Bool) -> Void = { _ in self.labelContainer.isHidden = true }
let noAnimate = { animate(); completion(true) }
if animated {
UIView.animate(withDuration: 0.3, animations: animate, completion: nil)
} else {
noAnimate()
}
}

private func hideComments(animated: Bool = true) {
self.labelContainer.isHidden = false
self.showCommentView.isActive = false
self.hideCommentView.isActive = true
self.ratingCommentsSpacing.constant = ConstraintSpacing.further.rawValue
preferredContentSize.height = self.height(for: .normal)

let animate = {
self.view.layoutIfNeeded()
self.commentViewContainer.alpha = 0.0
self.labelContainer.alpha = 1.0
}

let completion: (Bool) -> Void = { _ in self.commentViewContainer.isHidden = true }
let noAnimation = { animate(); completion(true) }
if animated {
UIView.animate(withDuration: 0.3, animations: animate, completion: nil)
} else { noAnimation() }
}

private func height(for height: ContainerHeight) -> CGFloat {
let window = UIApplication.shared.keyWindow
let bottomMargin = window!.safeAreaInsets.bottom
return height.rawValue + bottomMargin
}

private func updateInterface() {
guard let name = destination?.name?.nonEmptyString else { return self.styleForUnnamedDestination() }
self.primary.text = name
}

private func clearInterface() {
self.primary.text = nil
self.stars.rating = 0
}

private func styleForUnnamedDestination() {
self.staticYouHaveArrived.alpha = 0.0
self.primary.text = NSLocalizedString("END_OF_ROUTE_ARRIVED", bundle: .mapboxNavigation, value: "You have arrived", comment: "Title used for arrival")
}

private func setPlaceholderText() {
self.commentView.text = self.placeholder
}
}

// MARK: - UITextViewDelegate

extension EndOfRouteViewController: UITextViewDelegate {
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
guard text.count == 1, text.rangeOfCharacter(from: CharacterSet.newlines) != nil else { return true }
textView.resignFirstResponder()
return false
}

func textViewDidChange(_ textView: UITextView) {
self.comment = textView.text // Bind data model
}

func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == self.placeholder {
textView.text = nil
textView.alpha = 1.0
}
textView.becomeFirstResponder()
}

func textViewDidEndEditing(_ textView: UITextView) {
if (textView.text?.isEmpty ?? true) == true {
textView.text = self.placeholder
textView.alpha = 0.9
guard let name = destination?.name?.nonEmptyString else {
self.staticYouHaveArrived.alpha = 0.0
self.primaryLabel.text = self.endOfRouteArrivedText
return
}
self.staticYouHaveArrived.alpha = 1.0
self.primaryLabel.text = name
}

private func activateLayoutConstraints() {
NSLayoutConstraint.activate([
self.column.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16),
self.column.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -8),
self.column.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
self.column.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16),
self.endNavigationButton.heightAnchor.constraint(equalToConstant: 60),
self.endNavigationButton.leadingAnchor.constraint(equalTo: self.column.leadingAnchor),
self.endNavigationButton.trailingAnchor.constraint(equalTo: self.column.trailingAnchor)
])
}
}
Loading

0 comments on commit 411a1f2

Please sign in to comment.