mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-20 13:23:59 +00:00
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>
244 lines
7.2 KiB
Swift
244 lines
7.2 KiB
Swift
protocol ActionBarViewControllerDelegate: AnyObject {
|
|
func actionBar(_ actionBar: ActionBarViewController, didPressButton type: ActionBarButtonType)
|
|
}
|
|
|
|
final class ActionBarViewController: UIViewController {
|
|
@IBOutlet var stackView: UIStackView!
|
|
private(set) var downloadButton: ActionBarButton? = nil
|
|
private(set) var bookmarkButton: ActionBarButton? = nil
|
|
private var popoverSourceView: UIView? {
|
|
stackView.arrangedSubviews.last
|
|
}
|
|
|
|
var placePageData: PlacePageData!
|
|
var isRoutePlanning = false
|
|
var canAddStop = false
|
|
|
|
private var visibleButtons: [ActionBarButtonType] = []
|
|
private var additionalButtons: [ActionBarButtonType] = []
|
|
|
|
weak var delegate: ActionBarViewControllerDelegate?
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
configureButtons()
|
|
}
|
|
|
|
// MARK: - Private methods
|
|
|
|
private func configureButtons() {
|
|
if placePageData.isRoutePoint {
|
|
visibleButtons.append(.routeRemoveStop)
|
|
} else if placePageData.roadType != .none {
|
|
switch placePageData.roadType {
|
|
case .toll:
|
|
visibleButtons.append(.avoidToll)
|
|
case .ferry:
|
|
visibleButtons.append(.avoidFerry)
|
|
case .dirty:
|
|
visibleButtons.append(.avoidDirty)
|
|
default:
|
|
fatalError()
|
|
}
|
|
} else {
|
|
configButton1()
|
|
configButton2()
|
|
configButton3()
|
|
configButton4()
|
|
}
|
|
|
|
setupButtonsState()
|
|
}
|
|
|
|
private func configButton1() {
|
|
if let mapNodeAttributes = placePageData.mapNodeAttributes {
|
|
switch mapNodeAttributes.nodeStatus {
|
|
case .onDiskOutOfDate, .onDisk, .undefined:
|
|
break
|
|
case .downloading, .applying, .inQueue, .error, .notDownloaded, .partly:
|
|
visibleButtons.append(.download)
|
|
return
|
|
@unknown default:
|
|
fatalError()
|
|
}
|
|
}
|
|
|
|
var buttons: [ActionBarButtonType] = []
|
|
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()
|
|
}
|
|
|
|
guard !buttons.isEmpty else { return }
|
|
visibleButtons.append(buttons[0])
|
|
if buttons.count > 1 {
|
|
additionalButtons.append(contentsOf: buttons.suffix(from: 1))
|
|
}
|
|
}
|
|
|
|
private func configButton2() {
|
|
var buttons: [ActionBarButtonType] = []
|
|
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:
|
|
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))
|
|
}
|
|
}
|
|
|
|
private func configButton3() {
|
|
switch placePageData.objectType {
|
|
case .POI, .bookmark, .track:
|
|
visibleButtons.append(.routeTo)
|
|
case .trackRecording:
|
|
break
|
|
@unknown default:
|
|
fatalError()
|
|
}
|
|
}
|
|
|
|
private func configButton4() {
|
|
guard !additionalButtons.isEmpty else { return }
|
|
additionalButtons.count == 1 ? visibleButtons.append(additionalButtons[0]) : visibleButtons.append(.more)
|
|
}
|
|
|
|
private func setupButtonsState() {
|
|
for buttonType in visibleButtons {
|
|
let (selected, enabled) = buttonState(buttonType)
|
|
let button = ActionBarButton(delegate: self,
|
|
buttonType: buttonType,
|
|
isSelected: selected,
|
|
isEnabled: enabled)
|
|
stackView.addArrangedSubview(button)
|
|
switch buttonType {
|
|
case .download:
|
|
downloadButton = button
|
|
updateDownloadButtonState(placePageData.mapNodeAttributes!.nodeStatus)
|
|
case .bookmark:
|
|
bookmarkButton = button
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
private func buttonState(_ buttonType: ActionBarButtonType) -> (selected: Bool, enabled: Bool) {
|
|
var selected = false
|
|
let enabled = true
|
|
switch buttonType {
|
|
case .bookmark:
|
|
selected = placePageData.bookmarkData != nil
|
|
case .track:
|
|
selected = placePageData.trackData != nil
|
|
default:
|
|
break
|
|
}
|
|
return (selected, enabled)
|
|
}
|
|
|
|
private func showMore() {
|
|
let actionSheet = UIAlertController(title: placePageData.previewData.title,
|
|
message: placePageData.previewData.subtitle,
|
|
preferredStyle: .actionSheet)
|
|
for button in additionalButtons {
|
|
let (selected, enabled) = buttonState(button)
|
|
let action = UIAlertAction(title: titleForButton(button, selected),
|
|
style: .default,
|
|
handler: { [weak self] _ in
|
|
guard let self = self else { return }
|
|
self.delegate?.actionBar(self, didPressButton: button)
|
|
})
|
|
action.isEnabled = enabled
|
|
actionSheet.addAction(action)
|
|
}
|
|
actionSheet.addAction(UIAlertAction(title: L("cancel"), style: .cancel))
|
|
if let popover = actionSheet.popoverPresentationController, let sourceView = stackView.arrangedSubviews.last {
|
|
popover.sourceView = sourceView
|
|
popover.sourceRect = sourceView.bounds
|
|
}
|
|
present(actionSheet, animated: true)
|
|
}
|
|
|
|
|
|
// MARK: - Public methods
|
|
|
|
func resetButtons() {
|
|
stackView.arrangedSubviews.forEach {
|
|
stackView.removeArrangedSubview($0)
|
|
$0.removeFromSuperview()
|
|
}
|
|
visibleButtons.removeAll()
|
|
additionalButtons.removeAll()
|
|
downloadButton = nil
|
|
bookmarkButton = nil
|
|
configureButtons()
|
|
}
|
|
|
|
func updateDownloadButtonState(_ nodeStatus: MapNodeStatus) {
|
|
guard let downloadButton = downloadButton, let mapNodeAttributes = placePageData.mapNodeAttributes else { return }
|
|
switch mapNodeAttributes.nodeStatus {
|
|
case .downloading:
|
|
downloadButton.mapDownloadProgress?.state = .progress
|
|
case .applying, .inQueue:
|
|
downloadButton.mapDownloadProgress?.state = .spinner
|
|
case .error:
|
|
downloadButton.mapDownloadProgress?.state = .failed
|
|
case .onDisk, .undefined, .onDiskOutOfDate:
|
|
downloadButton.mapDownloadProgress?.state = .completed
|
|
case .notDownloaded, .partly:
|
|
downloadButton.mapDownloadProgress?.state = .normal
|
|
@unknown default:
|
|
fatalError()
|
|
}
|
|
}
|
|
|
|
func updateBookmarkButtonState(isSelected: Bool) {
|
|
guard let bookmarkButton else { return }
|
|
if !isSelected && BookmarksManager.shared().hasRecentlyDeletedBookmark() {
|
|
bookmarkButton.setBookmarkButtonState(.recover)
|
|
return
|
|
}
|
|
bookmarkButton.setBookmarkButtonState(isSelected ? .delete : .save)
|
|
}
|
|
}
|
|
|
|
extension ActionBarViewController: ActionBarButtonDelegate {
|
|
func tapOnButton(with type: ActionBarButtonType) {
|
|
switch type {
|
|
case .more:
|
|
showMore()
|
|
default:
|
|
delegate?.actionBar(self, didPressButton: type)
|
|
}
|
|
}
|
|
}
|