解决UI的布局问题
This commit is contained in:
parent
21be7cef58
commit
e4a0728345
@ -16,7 +16,14 @@ class AppContext {
|
||||
var networkContext: SDLAPIClient.NetworkContext = .default()
|
||||
|
||||
// 当前app所处的场景
|
||||
var appScene: AppScene = .login(username: nil)
|
||||
var loginScene: LoginScene = .login(username: nil)
|
||||
|
||||
// 当前的场景
|
||||
enum LoginScene: Equatable {
|
||||
case login(username: String?)
|
||||
case register
|
||||
case resetPassword
|
||||
}
|
||||
|
||||
// 登陆凭证
|
||||
var loginCredit: Credit?
|
||||
@ -40,14 +47,6 @@ class AppContext {
|
||||
}
|
||||
}
|
||||
|
||||
// 当前的场景
|
||||
enum AppScene: Equatable {
|
||||
case login(username: String?)
|
||||
case logined
|
||||
case register
|
||||
case resetPassword
|
||||
}
|
||||
|
||||
init(noticePort: Int) {
|
||||
self.noticePort = noticePort
|
||||
}
|
||||
|
||||
@ -77,7 +77,6 @@ struct LoginView: View {
|
||||
}
|
||||
.padding(.bottom, 20)
|
||||
}
|
||||
.frame(width: 380, height: 520)
|
||||
}
|
||||
|
||||
}
|
||||
@ -106,7 +105,7 @@ struct LoginAccountView: View {
|
||||
HStack {
|
||||
Button("注册") {
|
||||
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
|
||||
self.appContext.appScene = .register
|
||||
self.appContext.loginScene = .register
|
||||
}
|
||||
}
|
||||
.buttonStyle(.link)
|
||||
@ -115,7 +114,7 @@ struct LoginAccountView: View {
|
||||
|
||||
Button("忘记密码?") {
|
||||
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
|
||||
self.appContext.appScene = .resetPassword
|
||||
self.appContext.loginScene = .resetPassword
|
||||
}
|
||||
}
|
||||
.buttonStyle(.link)
|
||||
@ -170,7 +169,7 @@ struct LoginAccountView: View {
|
||||
do {
|
||||
_ = try await appContext.loginWith(username: username, password: password)
|
||||
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
|
||||
self.appContext.appScene = .logined
|
||||
//self.appContext.appScene = .logined
|
||||
}
|
||||
} catch let err as SDLAPIError {
|
||||
self.showAlert = true
|
||||
@ -231,7 +230,7 @@ struct LoginTokenView: View {
|
||||
do {
|
||||
_ = try await appContext.loginWith(token: token)
|
||||
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
|
||||
self.appContext.appScene = .logined
|
||||
//self.appContext.appScene = .logined
|
||||
}
|
||||
} catch let err as SDLAPIError {
|
||||
self.showAlert = true
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct RootView: View {
|
||||
struct LoginRootView: View {
|
||||
@Environment(AppContext.self) var appContext: AppContext
|
||||
@State private var updateManager = AppUpdateManager.shared
|
||||
|
||||
@ -16,13 +16,10 @@ struct RootView: View {
|
||||
// 1. 主要界面容器
|
||||
// 使用 ZStack 代替 Group,因为它在处理内容对齐和转场重叠时更稳定
|
||||
ZStack(alignment: .center) {
|
||||
switch appContext.appScene {
|
||||
switch appContext.loginScene {
|
||||
case .login(username: let username):
|
||||
LoginView(username: username)
|
||||
.id("scene_login") // 显式 ID 确保转场触发
|
||||
case .logined:
|
||||
NetworkView()
|
||||
.id("scene_logined")
|
||||
case .register:
|
||||
RegisterRootView()
|
||||
.id("scene_register")
|
||||
@ -32,9 +29,7 @@ struct RootView: View {
|
||||
}
|
||||
}
|
||||
// 2. 关键:设置容器尺寸行为
|
||||
// 如果是全屏应用,用 maxWidth/Height .infinity
|
||||
// 如果是固定大小窗口,可以在这里写死 minWidth/minHeight
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.frame(width: 380, height: 500)
|
||||
// 3. 限制裁剪,防止位移动画超出 RootView 的边界
|
||||
.clipped()
|
||||
.transition(.asymmetric(
|
||||
@ -48,7 +43,7 @@ struct RootView: View {
|
||||
}
|
||||
}
|
||||
// 4. 统一处理 Scene 切换的动画
|
||||
.animation(.spring(duration: 0.5), value: appContext.appScene)
|
||||
.animation(.spring(duration: 0.5), value: appContext.loginScene)
|
||||
.animation(.spring(duration: 0.4), value: updateManager.showUpdateOverlay)
|
||||
// 关键:macOS 标准毛玻璃背景
|
||||
.background(VisualEffectView(material: .hudWindow, blendingMode: .behindWindow))
|
||||
@ -82,8 +77,5 @@ struct RootView: View {
|
||||
))
|
||||
.zIndex(100) // 确保更新遮罩永远在最上层
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
RootView()
|
||||
|
||||
}
|
||||
@ -14,21 +14,25 @@ struct RegisterRootView: View {
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .center) {
|
||||
switch registerModel.stage {
|
||||
case .requestVerifyCode:
|
||||
RegisterRequestVerifyCodeView()
|
||||
case .submitVerifyCode:
|
||||
RegisterSubmitVerifyCodeView()
|
||||
case .setPassword:
|
||||
RegisterSetPasswordView()
|
||||
case .success:
|
||||
RegisterSuccessView()
|
||||
Color.clear
|
||||
|
||||
ZStack(alignment: .center) {
|
||||
switch registerModel.stage {
|
||||
case .requestVerifyCode:
|
||||
RegisterRequestVerifyCodeView()
|
||||
case .submitVerifyCode:
|
||||
RegisterSubmitVerifyCodeView()
|
||||
case .setPassword:
|
||||
RegisterSetPasswordView()
|
||||
case .success:
|
||||
RegisterSuccessView()
|
||||
}
|
||||
}
|
||||
.transition(.asymmetric(
|
||||
insertion: .move(edge: registerModel.transitionEdge).combined(with: .opacity),
|
||||
removal: .move(edge: registerModel.transitionEdge == .trailing ? .leading : .trailing).combined(with: .opacity)
|
||||
))
|
||||
}
|
||||
.transition(.asymmetric(
|
||||
insertion: .move(edge: registerModel.transitionEdge).combined(with: .opacity),
|
||||
removal: .move(edge: registerModel.transitionEdge == .trailing ? .leading : .trailing).combined(with: .opacity)
|
||||
))
|
||||
.environment(registerModel)
|
||||
// --- 核心改动:使用 overlay ---
|
||||
.overlay(alignment: .topLeading) {
|
||||
@ -40,7 +44,7 @@ struct RegisterRootView: View {
|
||||
Button(action: {
|
||||
// 执行返回逻辑,例如重置到登录
|
||||
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
|
||||
self.appContext.appScene = .login(username: nil)
|
||||
self.appContext.loginScene = .login(username: nil)
|
||||
}
|
||||
}) {
|
||||
HStack {
|
||||
@ -127,8 +131,6 @@ struct RegisterRequestVerifyCodeView: View {
|
||||
.controlSize(.large)
|
||||
.frame(width: 280)
|
||||
.disabled(!SDLUtil.isValidIdentifyContact(model.username) || isProcessing)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(40)
|
||||
.alert(isPresented: $showAlert) {
|
||||
@ -244,8 +246,6 @@ struct RegisterSubmitVerifyCodeView: View {
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.frame(width: 280)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(40)
|
||||
.alert(isPresented: $showAlert) {
|
||||
@ -362,8 +362,6 @@ struct RegisterSetPasswordView: View {
|
||||
.controlSize(.large)
|
||||
.frame(width: 280)
|
||||
.disabled(passwordError != nil)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(40)
|
||||
.alert(isPresented: $showAlert) {
|
||||
@ -441,7 +439,7 @@ struct RegisterSuccessView: View {
|
||||
Button(action: {
|
||||
// 关闭当前注册窗口
|
||||
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
|
||||
self.appContext.appScene = .login(username: registerModel.username)
|
||||
self.appContext.loginScene = .login(username: registerModel.username)
|
||||
}
|
||||
}) {
|
||||
Text("立即开始使用")
|
||||
|
||||
@ -14,21 +14,25 @@ struct ResetPasswordRootView: View {
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .center) {
|
||||
switch resetPasswordModel.stage {
|
||||
case .requestVerifyCode:
|
||||
GetVerifyCodeView()
|
||||
case .submitVerifyCode:
|
||||
SubmitVerifyCodeView()
|
||||
case .resetPassword:
|
||||
ResetPasswordView()
|
||||
case .success:
|
||||
ResetPasswordSuccessView()
|
||||
Color.clear
|
||||
|
||||
ZStack(alignment: .center) {
|
||||
switch resetPasswordModel.stage {
|
||||
case .requestVerifyCode:
|
||||
GetVerifyCodeView()
|
||||
case .submitVerifyCode:
|
||||
SubmitVerifyCodeView()
|
||||
case .resetPassword:
|
||||
ResetPasswordView()
|
||||
case .success:
|
||||
ResetPasswordSuccessView()
|
||||
}
|
||||
}
|
||||
.transition(.asymmetric(
|
||||
insertion: .move(edge: resetPasswordModel.transitionEdge).combined(with: .opacity),
|
||||
removal: .move(edge: resetPasswordModel.transitionEdge == .trailing ? .leading : .trailing).combined(with: .opacity)
|
||||
))
|
||||
}
|
||||
.transition(.asymmetric(
|
||||
insertion: .move(edge: resetPasswordModel.transitionEdge).combined(with: .opacity),
|
||||
removal: .move(edge: resetPasswordModel.transitionEdge == .trailing ? .leading : .trailing).combined(with: .opacity)
|
||||
))
|
||||
.environment(resetPasswordModel)
|
||||
.overlay(alignment: .topLeading) {
|
||||
// 仅在非成功页面显示返回按钮
|
||||
@ -36,7 +40,7 @@ struct ResetPasswordRootView: View {
|
||||
Button(action: {
|
||||
// 执行返回逻辑,例如重置到登录
|
||||
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
|
||||
self.appContext.appScene = .login(username: nil)
|
||||
self.appContext.loginScene = .login(username: nil)
|
||||
}
|
||||
}) {
|
||||
HStack {
|
||||
@ -86,8 +90,6 @@ struct GetVerifyCodeView: View {
|
||||
.controlSize(.large)
|
||||
.frame(width: 280)
|
||||
.disabled(!SDLUtil.isValidIdentifyContact(model.username) || isProcessing)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(40)
|
||||
.alert(isPresented: $showAlert) {
|
||||
@ -179,8 +181,6 @@ struct SubmitVerifyCodeView: View {
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.frame(width: 280)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(40)
|
||||
.task {
|
||||
@ -294,8 +294,6 @@ struct ResetPasswordView: View {
|
||||
.controlSize(.large)
|
||||
.frame(width: 280)
|
||||
.disabled(!isInputValid || isProcessing)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(40)
|
||||
.alert(isPresented: $showAlert) {
|
||||
@ -364,7 +362,7 @@ struct ResetPasswordSuccessView: View {
|
||||
|
||||
Button(action: {
|
||||
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
|
||||
self.appContext.appScene = .login(username: self.resetPasswordModel.username)
|
||||
self.appContext.loginScene = .login(username: self.resetPasswordModel.username)
|
||||
}
|
||||
}) {
|
||||
Text("返回登录")
|
||||
@ -377,8 +375,6 @@ struct ResetPasswordSuccessView: View {
|
||||
}
|
||||
.opacity(animateText ? 1.0 : 0.0)
|
||||
.offset(y: animateText ? 0 : 20)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(40)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
|
||||
@ -43,8 +43,8 @@ struct punchnetApp: App {
|
||||
}
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup(id: "main") {
|
||||
RootView()
|
||||
Window("登陆", id: "login") {
|
||||
LoginRootView()
|
||||
.navigationTitle("")
|
||||
.environment(self.appContext)
|
||||
.onAppear {
|
||||
@ -59,6 +59,14 @@ struct punchnetApp: App {
|
||||
.windowToolbarStyle(.unified)
|
||||
.defaultPosition(.center)
|
||||
|
||||
Window("网络", id: "logined") {
|
||||
SettingsView()
|
||||
.environment(self.appContext)
|
||||
.frame(width: 750, height: 500)
|
||||
}
|
||||
.windowResizability(.contentSize)
|
||||
.defaultPosition(.center)
|
||||
|
||||
Window("设置", id: "settings") {
|
||||
SettingsView()
|
||||
.environment(self.appContext)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user