co-maps/iphone/Maps/UI/Search/SearchOnMap/SearchOnMapInteractor.swift

177 lines
5.5 KiB
Swift
Raw Normal View History

2025-11-22 13:58:55 +01:00
final class SearchOnMapInteractor: NSObject {
private let presenter: SearchOnMapPresenter
private let searchManager: SearchManager.Type
private let routeManager: MWMRouter.Type
private var isUpdatesDisabled = false
var routingTooltipSearch: SearchOnMapRoutingTooltipSearch = .none
init(presenter: SearchOnMapPresenter,
searchManager: SearchManager.Type = Search.self,
routeManager: MWMRouter.Type = MWMRouter.self) {
self.presenter = presenter
self.searchManager = searchManager
self.routeManager = routeManager
super.init()
searchManager.add(self)
}
deinit {
searchManager.remove(self)
}
func handle(_ event: SearchOnMap.Request) {
let response = resolve(event)
presenter.process(response)
}
private func resolve(_ event: SearchOnMap.Request) -> SearchOnMap.Response {
switch event {
case .openSearch:
return .showHistoryAndCategory
case .hideSearch:
return .setSearchScreenHidden(true)
case .didStartDraggingSearch:
return .setIsTyping(false)
case .didStartTyping:
return .setIsTyping(true)
case .didType(let searchText):
return processTypedText(searchText)
case .clearButtonDidTap:
return processClearButtonDidTap()
case .didSelect(let searchText):
return processSelectedText(searchText)
case .searchButtonDidTap(let searchText):
return processSearchButtonDidTap(searchText)
case .didSelectResult(let result, let query):
return processSelectedResult(result, query: query)
case .didSelectPlaceOnMap:
return isiPad ? .none : .setSearchScreenHidden(true)
case .didDeselectPlaceOnMap:
return deselectPlaceOnMap()
case .didStartDraggingMap:
return .setSearchScreenCompact
case .didUpdatePresentationStep(let step):
searchManager.setSearchMode(searchModeForPresentationStep(step))
return .updatePresentationStep(step)
case .closeSearch:
return closeSearch()
}
}
private func processClearButtonDidTap() -> SearchOnMap.Response {
isUpdatesDisabled = true
searchManager.clear()
return .clearSearch
}
private func processSearchButtonDidTap(_ query: SearchQuery) -> SearchOnMap.Response {
searchManager.save(query)
return .showOnTheMap
}
private func processTypedText(_ query: SearchQuery) -> SearchOnMap.Response {
isUpdatesDisabled = false
searchManager.searchQuery(query)
return .startSearching
}
private func processSelectedText(_ query: SearchQuery) -> SearchOnMap.Response {
isUpdatesDisabled = false
if query.source != .history {
searchManager.save(query)
}
searchManager.searchQuery(query)
return .selectQuery(query)
}
private func processSelectedResult(_ result: SearchResult, query: SearchQuery) -> SearchOnMap.Response {
switch result.itemType {
case .regular:
searchManager.save(query)
switch routingTooltipSearch {
case .none:
searchManager.showResult(at: result.index)
case .start:
let point = MWMRoutePoint(cgPoint: result.point,
title: result.titleText,
subtitle: result.addressText,
type: .start,
intermediateIndex: 0)
routeManager.build(from: point, bestRouter: false)
case .finish:
let point = MWMRoutePoint(cgPoint: result.point,
title: result.titleText,
subtitle: result.addressText,
type: .finish,
intermediateIndex: 0)
routeManager.build(to: point, bestRouter: false)
@unknown default:
fatalError("Unsupported routingTooltipSearch")
}
return isiPad ? .none : .setSearchScreenHidden(true)
case .suggestion:
let suggestionQuery = SearchQuery(result.suggestion,
locale: query.locale,
source: result.isPureSuggest ? .suggestion : .typedText)
searchManager.searchQuery(suggestionQuery)
return .selectQuery(suggestionQuery)
@unknown default:
fatalError("Unsupported result type")
}
}
private func deselectPlaceOnMap() -> SearchOnMap.Response {
routingTooltipSearch = .none
return .setSearchScreenHidden(false)
}
private func closeSearch() -> SearchOnMap.Response {
routingTooltipSearch = .none
isUpdatesDisabled = true
searchManager.clear()
return .close
}
private func searchModeForPresentationStep(_ step: ModalPresentationStep) -> SearchMode {
switch step {
case .fullScreen:
return isiPad ? .everywhereAndViewport : .everywhere
case .halfScreen, .compact:
return .everywhereAndViewport
case .hidden:
return .viewport
}
}
}
// MARK: - MWMSearchObserver
extension SearchOnMapInteractor: MWMSearchObserver {
func onSearchCompleted() {
guard !isUpdatesDisabled, searchManager.searchMode() != .viewport else { return }
let results = searchManager.getResults()
presenter.process(.showResults(SearchOnMap.SearchResults(results), isSearchCompleted: true))
}
func onSearchResultsUpdated() {
guard !isUpdatesDisabled, searchManager.searchMode() != .viewport else { return }
let results = searchManager.getResults()
guard !results.isEmpty else { return }
presenter.process(.showResults(SearchOnMap.SearchResults(results), isSearchCompleted: false))
}
}