Initial commit: suixinkan_ios UIKit rewrite project.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
138
suixinkan_ios/App/ViewControllers/RootViewController.swift
Normal file
138
suixinkan_ios/App/ViewControllers/RootViewController.swift
Normal file
@ -0,0 +1,138 @@
|
||||
//
|
||||
// RootViewController.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import SnapKit
|
||||
import UIKit
|
||||
|
||||
@MainActor
|
||||
/// 应用根 ViewController,根据登录阶段切换子页面并挂载全局 Overlay。
|
||||
final class RootViewController: UIViewController {
|
||||
|
||||
private let services: AppServices
|
||||
private var currentChild: UIViewController?
|
||||
private let restoringView = UIView()
|
||||
|
||||
init(services: AppServices = .shared) {
|
||||
self.services = services
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
view.backgroundColor = .systemBackground
|
||||
restoringView.backgroundColor = .systemBackground
|
||||
|
||||
services.appSession.onChange = { [weak self] in
|
||||
self?.handleSessionPhaseChange()
|
||||
}
|
||||
|
||||
mountChild(for: services.appSession.phase)
|
||||
bootstrapSession()
|
||||
configurePushNotifications()
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
attachGlobalOverlays()
|
||||
}
|
||||
|
||||
private func bootstrapSession() {
|
||||
Task {
|
||||
await services.globalLoading.withLoading {
|
||||
await services.sessionBootstrapper.restore(
|
||||
appSession: services.appSession,
|
||||
accountContext: services.accountContext,
|
||||
permissionContext: services.permissionContext,
|
||||
profileAPI: services.profileAPI,
|
||||
accountContextAPI: services.accountContextAPI,
|
||||
toastCenter: services.toastCenter
|
||||
)
|
||||
}
|
||||
|
||||
if services.appSession.isLoggedIn, !AppUITestLaunchState.isRunningUITests {
|
||||
PushNotificationManager.shared.requestAuthorizationAndRegister()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func configurePushNotifications() {
|
||||
services.configurePushNotifications()
|
||||
}
|
||||
|
||||
private func attachGlobalOverlays() {
|
||||
guard let window = view.window else { return }
|
||||
services.toastCenter.attachToWindow(window)
|
||||
services.globalLoading.attachToWindow(window)
|
||||
}
|
||||
|
||||
private func handleSessionPhaseChange() {
|
||||
mountChild(for: services.appSession.phase)
|
||||
|
||||
switch services.appSession.phase {
|
||||
case .loggedIn:
|
||||
if !AppUITestLaunchState.isRunningUITests {
|
||||
PushNotificationManager.shared.requestAuthorizationAndRegister()
|
||||
}
|
||||
Task { await reloadScenicSpotContextIfNeeded() }
|
||||
case .loggedOut:
|
||||
services.accountContext.reset()
|
||||
services.permissionContext.reset()
|
||||
services.scenicSpotContext.reset()
|
||||
services.appRouter.reset()
|
||||
services.toastCenter.dismiss()
|
||||
services.scenicQueueRuntime.stop()
|
||||
case .restoring:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private func reloadScenicSpotContextIfNeeded() async {
|
||||
guard services.appSession.isLoggedIn else {
|
||||
services.scenicSpotContext.reset()
|
||||
return
|
||||
}
|
||||
await services.scenicSpotContext.reload(
|
||||
scenicId: services.accountContext.currentScenic?.id,
|
||||
api: services.accountContextAPI
|
||||
)
|
||||
}
|
||||
|
||||
private func mountChild(for phase: AuthPhase) {
|
||||
let nextChild: UIViewController
|
||||
switch phase {
|
||||
case .loggedOut:
|
||||
nextChild = LoginViewController(services: services)
|
||||
case .restoring:
|
||||
nextChild = restoringViewController()
|
||||
case .loggedIn:
|
||||
nextChild = MainTabBarController(services: services)
|
||||
}
|
||||
|
||||
guard currentChild !== nextChild else { return }
|
||||
|
||||
currentChild?.willMove(toParent: nil)
|
||||
currentChild?.view.removeFromSuperview()
|
||||
currentChild?.removeFromParent()
|
||||
|
||||
addChild(nextChild)
|
||||
view.addSubview(nextChild.view)
|
||||
nextChild.view.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
nextChild.didMove(toParent: self)
|
||||
currentChild = nextChild
|
||||
}
|
||||
|
||||
private func restoringViewController() -> UIViewController {
|
||||
let controller = UIViewController()
|
||||
controller.view.backgroundColor = .systemBackground
|
||||
return controller
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user