181 lines
5.7 KiB
Swift
181 lines
5.7 KiB
Swift
//
|
|
// HomeViewController.swift
|
|
// QuickLocation
|
|
//
|
|
// Created by 八条 on 2026/5/27.
|
|
//
|
|
|
|
import UIKit
|
|
import RxSwift
|
|
import CoreLocation
|
|
#if !targetEnvironment(simulator)
|
|
import MAMapKit
|
|
#endif
|
|
|
|
class HomeViewController: BaseViewController {
|
|
|
|
override var isNavigationBarHidden: Bool { true }
|
|
override var preferredStatusBarStyle: UIStatusBarStyle { .default }
|
|
|
|
// MARK: - Properties
|
|
fileprivate var rootView: HomeView!
|
|
private let locationManager = CLLocationManager()
|
|
private var currentHeading: Double = 0
|
|
private var members: [CircleMember] = []
|
|
private var currentUserMember: CircleMember?
|
|
|
|
override func loadView() {
|
|
#if !targetEnvironment(simulator)
|
|
MAMapView.updatePrivacyAgree(.didAgree)
|
|
MAMapView.updatePrivacyShow(.didShow, privacyInfo: .didContain)
|
|
#endif
|
|
|
|
rootView = HomeView(frame: UIScreen.main.bounds)
|
|
view = rootView
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
setupMap()
|
|
setupLocation()
|
|
loadMembers()
|
|
|
|
requestUserInfo()
|
|
}
|
|
|
|
// MARK: - Map Setup
|
|
private func setupMap() {
|
|
#if !targetEnvironment(simulator)
|
|
rootView.mapView.delegate = self
|
|
|
|
let r = MAUserLocationRepresentation()
|
|
r.showsAccuracyRing = false
|
|
r.showsHeadingIndicator = false
|
|
rootView.mapView.update(r)
|
|
#endif
|
|
}
|
|
|
|
// MARK: - Location
|
|
private func setupLocation() {
|
|
locationManager.delegate = self
|
|
locationManager.desiredAccuracy = kCLLocationAccuracyBest
|
|
locationManager.requestWhenInUseAuthorization()
|
|
locationManager.startUpdatingHeading()
|
|
locationManager.startUpdatingLocation()
|
|
}
|
|
|
|
// MARK: - Members
|
|
private func loadMembers() {
|
|
members = .mock
|
|
currentUserMember = members.first { $0.isCurrentUser }
|
|
updateAnnotations()
|
|
centerOnMembers()
|
|
}
|
|
|
|
private func centerOnMembers() {
|
|
#if !targetEnvironment(simulator)
|
|
guard !members.isEmpty else { return }
|
|
if let current = currentUserMember {
|
|
rootView.mapView.setCenter(current.coordinate, animated: false)
|
|
} else if let first = members.first {
|
|
rootView.mapView.setCenter(first.coordinate, animated: false)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// MARK: - Annotations
|
|
private func updateAnnotations() {
|
|
#if !targetEnvironment(simulator)
|
|
let mapView = rootView.mapView
|
|
let existing = mapView.annotations ?? []
|
|
let existingMemberIDs = Set(existing.compactMap { ($0 as? MemberAnnotation)?.member.id })
|
|
let newMemberIDs = Set(members.map { $0.id })
|
|
|
|
let toRemove = existing.filter { ann in
|
|
guard let ma = ann as? MemberAnnotation else { return false }
|
|
return !newMemberIDs.contains(ma.member.id)
|
|
}
|
|
mapView.removeAnnotations(toRemove)
|
|
|
|
let toAdd = members.filter { !$0.isCurrentUser && !existingMemberIDs.contains($0.id) }
|
|
let annotations = toAdd.map { MemberAnnotation(member: $0) }
|
|
mapView.addAnnotations(annotations)
|
|
#endif
|
|
}
|
|
|
|
// MARK: - Heading
|
|
private func updateCurrentUserHeading() {
|
|
#if !targetEnvironment(simulator)
|
|
guard let annotations = rootView.mapView.annotations else { return }
|
|
for ann in annotations {
|
|
guard ann is MAUserLocation else { continue }
|
|
if let view = rootView.mapView.view(for: ann as! MAAnnotation) as? MemberAnnotationView {
|
|
view.updateHeading(currentHeading)
|
|
}
|
|
break
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// MARK: - API
|
|
private func requestUserInfo() {
|
|
UserService.userInfo().subscribe { response in
|
|
|
|
}.disposed(by: disposeBag)
|
|
}
|
|
}
|
|
|
|
#if !targetEnvironment(simulator)
|
|
// MARK: - MAMapViewDelegate
|
|
extension HomeViewController: MAMapViewDelegate {
|
|
|
|
func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! {
|
|
if annotation is MAUserLocation {
|
|
let identifier = "UserLocationAnnotation"
|
|
var view = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MemberAnnotationView
|
|
if view == nil {
|
|
view = MemberAnnotationView(annotation: annotation, reuseIdentifier: identifier)
|
|
}
|
|
if let currentUser = currentUserMember {
|
|
view?.configure(with: currentUser)
|
|
}
|
|
return view
|
|
}
|
|
|
|
guard let memberAnnotation = annotation as? MemberAnnotation else { return nil }
|
|
|
|
let identifier = "MemberAnnotation"
|
|
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? MemberAnnotationView
|
|
if annotationView == nil {
|
|
annotationView = MemberAnnotationView(annotation: memberAnnotation, reuseIdentifier: identifier)
|
|
} else {
|
|
annotationView?.annotation = memberAnnotation
|
|
}
|
|
|
|
annotationView?.configure(with: memberAnnotation.member)
|
|
return annotationView
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// MARK: - CLLocationManagerDelegate
|
|
extension HomeViewController: CLLocationManagerDelegate {
|
|
|
|
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
|
|
let h = newHeading.trueHeading
|
|
guard h >= 0 else { return }
|
|
currentHeading = h
|
|
updateCurrentUserHeading()
|
|
}
|
|
|
|
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
|
#if !targetEnvironment(simulator)
|
|
guard let location = locations.last else { return }
|
|
rootView.mapView.setCenter(location.coordinate, animated: true)
|
|
#endif
|
|
}
|
|
|
|
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
|
|
}
|
|
}
|