82 lines
3.0 KiB
Swift
82 lines
3.0 KiB
Swift
//
|
||
// RootView.swift
|
||
// punchnet
|
||
//
|
||
// Created by 安礼成 on 2026/1/19.
|
||
//
|
||
|
||
import SwiftUI
|
||
|
||
struct LoginRootView: View {
|
||
@Environment(AppContext.self) var appContext: AppContext
|
||
@State private var updateManager = AppUpdateManager.shared
|
||
|
||
var body: some View {
|
||
ZStack {
|
||
// 1. 主要界面容器
|
||
// 使用 ZStack 代替 Group,因为它在处理内容对齐和转场重叠时更稳定
|
||
ZStack(alignment: .center) {
|
||
switch appContext.loginScene {
|
||
case .login(username: let username):
|
||
LoginView(username: username)
|
||
.id("scene_login") // 显式 ID 确保转场触发
|
||
case .register:
|
||
RegisterRootView()
|
||
.id("scene_register")
|
||
case .resetPassword:
|
||
ResetPasswordRootView()
|
||
.id("scene_reset")
|
||
}
|
||
}
|
||
// 2. 关键:设置容器尺寸行为
|
||
.frame(width: 380, height: 500)
|
||
// 3. 限制裁剪,防止位移动画超出 RootView 的边界
|
||
.clipped()
|
||
.transition(.asymmetric(
|
||
insertion: .move(edge: .trailing).combined(with: .opacity),
|
||
removal: .move(edge: .leading).combined(with: .opacity) // 修改为 leading 更有“流转”感
|
||
))
|
||
|
||
// 自动更新遮罩层级
|
||
if updateManager.showUpdateOverlay, let info = updateManager.updateInfo {
|
||
updateOverlay(info: info)
|
||
}
|
||
}
|
||
// 4. 统一处理 Scene 切换的动画
|
||
.animation(.spring(duration: 0.5), value: appContext.loginScene)
|
||
.animation(.spring(duration: 0.4), value: updateManager.showUpdateOverlay)
|
||
// 关键:macOS 标准毛玻璃背景
|
||
.background(VisualEffectView(material: .hudWindow, blendingMode: .behindWindow))
|
||
.task {
|
||
let checkUpdateResult = await updateManager.checkUpdate(isManual: false)
|
||
NSLog("[RootView] checkUpdateResult: \(checkUpdateResult)")
|
||
}
|
||
}
|
||
|
||
// 将遮罩抽离,保持 body 清爽
|
||
@ViewBuilder
|
||
private func updateOverlay(info: SDLAPIClient.AppUpgradeInfo) -> some View {
|
||
ZStack {
|
||
Color.black.opacity(0.4)
|
||
.ignoresSafeArea()
|
||
.onTapGesture {
|
||
if !info.forceUpdate {
|
||
updateManager.showUpdateOverlay = false
|
||
}
|
||
}
|
||
|
||
AppUpdateView(info: info) {
|
||
updateManager.showUpdateOverlay = false
|
||
}
|
||
.clipShape(RoundedRectangle(cornerRadius: 16))
|
||
.shadow(color: .black.opacity(0.3), radius: 20)
|
||
}
|
||
.transition(.asymmetric(
|
||
insertion: .scale(scale: 0.9).combined(with: .opacity),
|
||
removal: .opacity
|
||
))
|
||
.zIndex(100) // 确保更新遮罩永远在最上层
|
||
}
|
||
|
||
}
|