同步相册云盘界面并完善相关交互

This commit is contained in:
2026-07-10 17:15:15 +08:00
parent ab5220e460
commit ceca780ab3
13 changed files with 2269 additions and 532 deletions

View File

@ -10,6 +10,8 @@ import UIKit
/// 线
final class WildReportRiskMapViewController: BaseViewController {
private static let cachedNavigationAppKey = "wildReportRiskMap.cachedNavigationApp"
private let viewModel: WildReportRiskMapViewModel
private let api: any WildPhotographerReportServing
private let locationProvider: any LocationProviding
@ -907,6 +909,10 @@ final class WildReportRiskMapViewController: BaseViewController {
return
}
guard let target = viewModel.navigateToSelectedMarker() else { return }
if let cachedOption = cachedNavigationOption(for: target) {
openNavigation(cachedOption, cacheSelection: false)
return
}
presentNavigationOptions(for: target)
}
@ -930,7 +936,7 @@ final class WildReportRiskMapViewController: BaseViewController {
let alert = UIAlertController(title: "选择导航软件", message: target.title, preferredStyle: .actionSheet)
options.forEach { option in
alert.addAction(UIAlertAction(title: option.title, style: .default) { [weak self] _ in
self?.openNavigation(option)
self?.openNavigation(option, cacheSelection: true)
})
}
alert.addAction(UIAlertAction(title: "取消", style: .cancel))
@ -942,43 +948,71 @@ final class WildReportRiskMapViewController: BaseViewController {
}
private func availableNavigationOptions(for target: WildReportMapMarker) -> [WildReportNavigationOption] {
[
WildReportNavigationOption(title: "Apple 地图", url: navigationURL(for: .apple, target: target)),
WildReportNavigationOption(title: "高德地图", url: navigationURL(for: .amap, target: target)),
WildReportNavigationOption(title: "百度地图", url: navigationURL(for: .baidu, target: target)),
WildReportNavigationOption(title: "腾讯地图", url: navigationURL(for: .tencent, target: target)),
WildReportNavigationOption(title: "Google Maps", url: navigationURL(for: .google, target: target))
].compactMap { option in
guard option.url != nil else { return nil }
WildReportNavigationApp.allCases.compactMap { app in
guard let option = navigationOption(for: app, target: target) else { return nil }
guard isNavigationOptionAvailable(option) else { return nil }
return option
}
}
private func openNavigation(_ option: WildReportNavigationOption) {
private func cachedNavigationOption(for target: WildReportMapMarker) -> WildReportNavigationOption? {
guard let rawValue = UserDefaults.standard.string(forKey: Self.cachedNavigationAppKey),
let app = WildReportNavigationApp(rawValue: rawValue),
let option = navigationOption(for: app, target: target),
isNavigationOptionAvailable(option)
else {
UserDefaults.standard.removeObject(forKey: Self.cachedNavigationAppKey)
return nil
}
return option
}
private func navigationOption(for app: WildReportNavigationApp, target: WildReportMapMarker) -> WildReportNavigationOption? {
WildReportNavigationOption(
app: app,
title: app.title,
url: navigationURL(for: app, target: target),
requiresAvailabilityCheck: app.requiresAvailabilityCheck
)
}
private func isNavigationOptionAvailable(_ option: WildReportNavigationOption) -> Bool {
guard let url = option.url else { return false }
return !option.requiresAvailabilityCheck || UIApplication.shared.canOpenURL(url)
}
private func openNavigation(_ option: WildReportNavigationOption, cacheSelection: Bool) {
guard let url = option.url else { return }
UIApplication.shared.open(url) { [weak self] success in
guard !success else { return }
guard success else {
UserDefaults.standard.removeObject(forKey: Self.cachedNavigationAppKey)
Task { @MainActor in
self?.showToast("无法打开\(option.title)")
}
return
}
guard cacheSelection else { return }
Task { @MainActor in
self?.showToast("未安装\(option.title)或无法打开")
UserDefaults.standard.set(option.app.rawValue, forKey: Self.cachedNavigationAppKey)
}
}
}
private func navigationURL(for app: WildReportNavigationApp, target: WildReportMapMarker) -> URL? {
let latitude = target.coordinate.latitude
let longitude = target.coordinate.longitude
let destLat = target.coordinate.latitude
let destLon = target.coordinate.longitude
let name = encodedNavigationText(target.title)
switch app {
case .apple:
return URL(string: "http://maps.apple.com/?daddr=\(latitude),\(longitude)&dirflg=d&q=\(name)")
return URL(string: "http://maps.apple.com/?daddr=\(destLat),\(destLon)&dirflg=d")
case .amap:
return URL(string: "iosamap://path?sourceApplication=suixinkan&dlat=\(latitude)&dlon=\(longitude)&dname=\(name)&dev=0&t=0")
return URL(string: "iosamap://path?sourceApplication=suixinkan&dlat=\(destLat)&dlon=\(destLon)&dname=\(name)&dev=0&t=0")
case .baidu:
return URL(string: "baidumap://map/direction?destination=latlng:\(latitude),\(longitude)|name:\(name)&mode=driving&coord_type=wgs84")
return URL(string: "baidumap://map/direction?destination=latlng:\(destLat),\(destLon)|name:\(name)&mode=driving&coord_type=wgs84")
case .tencent:
return URL(string: "qqmap://map/routeplan?type=drive&tocoord=\(latitude),\(longitude)&to=\(name)&referer=suixinkan")
return URL(string: "qqmap://map/routeplan?type=drive&tocoord=\(destLat),\(destLon)&to=\(name)&referer=suixinkan")
case .google:
return URL(string: "comgooglemaps://?daddr=\(latitude),\(longitude)&directionsmode=driving")
return URL(string: "comgooglemaps://?daddr=\(destLat),\(destLon)&directionsmode=driving")
}
}
@ -1022,17 +1056,40 @@ final class WildReportRiskMapViewController: BaseViewController {
}
}
///
private struct WildReportNavigationOption {
let app: WildReportNavigationApp
let title: String
let url: URL?
let requiresAvailabilityCheck: Bool
}
private enum WildReportNavigationApp {
///
private enum WildReportNavigationApp: String, CaseIterable {
case apple
case amap
case baidu
case tencent
case google
var title: String {
switch self {
case .apple:
return "Apple 地图"
case .amap:
return "高德地图"
case .baidu:
return "百度地图"
case .tencent:
return "腾讯地图"
case .google:
return "Google Maps"
}
}
var requiresAvailabilityCheck: Bool {
self != .apple
}
}
extension WildReportRiskMapViewController: MKMapViewDelegate {