This commit is contained in:
anlicheng 2026-03-24 15:10:58 +08:00
parent 97194e501e
commit 067ac7c092
5 changed files with 83 additions and 96 deletions

View File

@ -77,8 +77,6 @@ struct LoginView: View {
.padding(.bottom, 20) .padding(.bottom, 20)
} }
.frame(width: 380, height: 520) .frame(width: 380, height: 520)
// macOS
.background(VisualEffectView(material: .hudWindow, blendingMode: .behindWindow))
.ignoresSafeArea() .ignoresSafeArea()
} }
@ -288,25 +286,6 @@ struct CustomSecureField: View {
} }
} }
// MARK: - 1. UI ( Material )
struct VisualEffectView: NSViewRepresentable {
let material: NSVisualEffectView.Material
let blendingMode: NSVisualEffectView.BlendingMode
func makeNSView(context: Context) -> NSVisualEffectView {
let view = NSVisualEffectView()
view.material = material
view.blendingMode = blendingMode
view.state = .active
return view
}
func updateNSView(_ nsView: NSVisualEffectView, context: Context) {
nsView.material = material
nsView.blendingMode = blendingMode
}
}
#Preview { #Preview {
LoginView() LoginView()
.environment(AppContext(noticePort: 0)) .environment(AppContext(noticePort: 0))

View File

@ -14,11 +14,10 @@ struct RegisterRootView: View {
var body: some View { var body: some View {
ZStack { ZStack {
// Color.clear
VisualEffectView(material: .underWindowBackground, blendingMode: .behindWindow)
.ignoresSafeArea() .ignoresSafeArea()
Group { ZStack(alignment: .center) {
switch registerModel.stage { switch registerModel.stage {
case .requestVerifyCode: case .requestVerifyCode:
RegisterRequestVerifyCodeView() RegisterRequestVerifyCodeView()
@ -64,7 +63,6 @@ struct RegisterRootView: View {
.transition(.opacity) // .transition(.opacity) //
} }
} }
.frame(width: 500, height: 400)
} }
} }
@ -122,7 +120,9 @@ struct RegisterRequestVerifyCodeView: View {
.frame(width: 280) .frame(width: 280)
Button(action: { Button(action: {
self.requestVerifyCode(username: model.username) Task { @MainActor in
await self.requestVerifyCode(username: model.username)
}
}) { }) {
Text("获取验证码") Text("获取验证码")
.fontWeight(.medium) .fontWeight(.medium)
@ -141,40 +141,40 @@ struct RegisterRequestVerifyCodeView: View {
} }
} }
private func requestVerifyCode(username: String) { private func requestVerifyCode(username: String) async {
self.isProcessing = true self.isProcessing = true
Task { @MainActor in defer {
if username.isEmpty {
self.showAlert = true
self.errorMessage = "邮箱为空"
self.isProcessing = false
return
}
switch SDLUtil.identifyContact(username) {
case .email:
do {
let registerSession = try await self.registerModel.requestVerifyCode(username: username)
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.registerModel.stage = .submitVerifyCode
self.registerModel.username = username
self.registerModel.sessionId = registerSession.sessionId
self.registerModel.transitionEdge = .trailing
}
} catch let err as SDLAPIError {
self.showAlert = true
self.errorMessage = err.message
} catch let err {
self.showAlert = true
self.errorMessage = err.localizedDescription
}
default:
self.showAlert = true
self.errorMessage = "邮箱格式错误"
}
self.isProcessing = false self.isProcessing = false
} }
if username.isEmpty {
self.showAlert = true
self.errorMessage = "邮箱为空"
return
}
switch SDLUtil.identifyContact(username) {
case .email:
do {
let registerSession = try await self.registerModel.requestVerifyCode(username: username)
withAnimation(.spring(duration: 0.6, bounce: 0.2)) {
self.registerModel.stage = .submitVerifyCode
self.registerModel.username = username
self.registerModel.sessionId = registerSession.sessionId
self.registerModel.transitionEdge = .trailing
}
} catch let err as SDLAPIError {
self.showAlert = true
self.errorMessage = err.message
} catch let err {
self.showAlert = true
self.errorMessage = err.localizedDescription
}
default:
self.showAlert = true
self.errorMessage = "邮箱格式错误"
}
} }
} }

View File

@ -14,11 +14,10 @@ struct ResetPasswordRootView: View {
var body: some View { var body: some View {
ZStack { ZStack {
// (macOS ) Color.clear
VisualEffectView(material: .underWindowBackground, blendingMode: .behindWindow)
.ignoresSafeArea() .ignoresSafeArea()
Group { ZStack(alignment: .center) {
switch resetPasswordModel.stage { switch resetPasswordModel.stage {
case .requestVerifyCode: case .requestVerifyCode:
GetVerifyCodeView() GetVerifyCodeView()
@ -60,7 +59,6 @@ struct ResetPasswordRootView: View {
.transition(.opacity) // .transition(.opacity) //
} }
} }
.frame(width: 500, height: 400)
} }
} }

View File

@ -9,60 +9,79 @@ import SwiftUI
struct RootView: View { struct RootView: View {
@Environment(AppContext.self) var appContext: AppContext @Environment(AppContext.self) var appContext: AppContext
@State private var updateManager = AppUpdateManager.shared @State private var updateManager = AppUpdateManager.shared
var body: some View { var body: some View {
ZStack { ZStack {
// // 1.
Group { // 使 ZStack Group
ZStack(alignment: .center) {
switch appContext.appScene { switch appContext.appScene {
case .login(username: let username): case .login(username: let username):
LoginView(username: username) LoginView(username: username)
.id("scene_login") // ID
case .logined: case .logined:
NetworkView() NetworkView()
.id("scene_logined")
case .register: case .register:
RegisterRootView() RegisterRootView()
.id("scene_register")
case .resetPassword: case .resetPassword:
ResetPasswordRootView() ResetPasswordRootView()
.id("scene_reset")
} }
} }
// 2.
// maxWidth/Height .infinity
// minWidth/minHeight
.frame(maxWidth: .infinity, maxHeight: .infinity)
// 3. RootView
.clipped()
.transition(.asymmetric( .transition(.asymmetric(
insertion: .move(edge: .trailing).combined(with: .opacity), insertion: .move(edge: .trailing).combined(with: .opacity),
removal: .move(edge: .trailing).combined(with: .opacity) removal: .move(edge: .leading).combined(with: .opacity) // leading
)) ))
// //
if updateManager.showUpdateOverlay, let info = updateManager.updateInfo { if updateManager.showUpdateOverlay, let info = updateManager.updateInfo {
// updateOverlay(info: info)
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
))
} }
} }
// 4. Scene
.animation(.spring(duration: 0.5), value: appContext.appScene)
.animation(.spring(duration: 0.4), value: updateManager.showUpdateOverlay) .animation(.spring(duration: 0.4), value: updateManager.showUpdateOverlay)
// macOS
.background(VisualEffectView(material: .hudWindow, blendingMode: .behindWindow))
.task { .task {
//
let checkUpdateResult = await updateManager.checkUpdate(isManual: false) let checkUpdateResult = await updateManager.checkUpdate(isManual: false)
NSLog("[RootView] checkUpdateResult: \(checkUpdateResult)") 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) //
}
} }
#Preview { #Preview {

View File

@ -55,16 +55,7 @@ struct punchnetApp: App {
//.interactiveDismissDisabled() // //.interactiveDismissDisabled() //
} }
} }
// .commands { .windowResizability(.contentSize)
// CommandGroup(replacing: .appInfo) {
// Button {
// openWindow(id: "abortPunchnet")
// } label: {
// Text("About Punchnet")
// }
// }
// }
//.windowResizability(.contentSize)
.windowToolbarStyle(.unified) .windowToolbarStyle(.unified)
.defaultPosition(.center) .defaultPosition(.center)