Files
e-party-iOS/yana/Views/LoginView.swift
edwinQQQ 3ec1b1302f feat: 更新iOS和Podfile的部署目标以支持新版本
- 将iOS平台版本更新至17,确保与最新的开发环境兼容。
- 更新Podfile中的iOS部署目标至17.0,确保依赖项与新版本兼容。
- 修改Podfile.lock以反映新的依赖项版本,确保项目一致性。
- 在多个视图中重构代码,优化状态管理和视图逻辑,提升用户体验。
2025-07-29 15:59:09 +08:00

195 lines
8.5 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import SwiftUI
import ComposableArchitecture
import Perception
// PreferenceKey
struct ImageHeightPreferenceKey: PreferenceKey {
static let defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = max(value, nextValue())
}
}
struct LoginView: View {
let store: StoreOf<LoginFeature>
let onLoginSuccess: () -> Void //
// 使@StateUI
@State private var showIDLogin: Bool = false
@State private var showEmailLogin: Bool = false
@State private var showLanguageSettings: Bool = false
@State private var showUserAgreement: Bool = false
@State private var showPrivacyPolicy: Bool = false
//
private var topImageHeight: CGFloat = 200 //
var body: some View {
WithPerceptionTracking {
NavigationStack {
GeometryReader { geometry in
ZStack {
// 使 splash
Image("bg")
.resizable()
.aspectRatio(contentMode: .fill)
.ignoresSafeArea(.all)
VStack(spacing: 0) {
// "top"
ZStack {
Image("top")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: .infinity)
.padding(.top, -100)
.background(
GeometryReader { topImageGeometry in
Color.clear.preference(key: ImageHeightPreferenceKey.self, value: topImageGeometry.size.height)
}
)
// E-PARTI "top"20
HStack {
Text(LocalizedString("login.app_title", comment: ""))
.font(FontManager.adaptedFont(.bayonRegular, designSize: 56, for: geometry.size.width))
.foregroundColor(.white)
.padding(.leading, 20)
Spacer()
}
.padding(.top, max(0, topImageHeight - 100)) // top - 140
}
//
VStack(spacing: 20) {
//
LoginButton(
title: LocalizedString("login.id_login", comment: ""),
icon: "person.circle",
action: {
showIDLogin = true
}
)
LoginButton(
title: LocalizedString("login.email_login", comment: ""),
icon: "envelope",
action: {
showEmailLogin = true
}
)
//
HStack(spacing: 20) {
Button(action: {
showLanguageSettings = true
}) {
Text(LocalizedString("login.language", comment: ""))
.font(.system(size: 14))
.foregroundColor(.white.opacity(0.8))
}
Button(action: {
showUserAgreement = true
}) {
Text(LocalizedString("login.user_agreement", comment: ""))
.font(.system(size: 14))
.foregroundColor(.white.opacity(0.8))
}
Button(action: {
showPrivacyPolicy = true
}) {
Text(LocalizedString("login.privacy_policy", comment: ""))
.font(.system(size: 14))
.foregroundColor(.white.opacity(0.8))
}
}
}
.padding(.horizontal, 28)
.padding(.bottom, 140)
}
// API Loading
APILoadingEffectView()
// NavigationLink navigationDestination
}
}
.navigationBarHidden(true)
// iOS 16 navigationDestination
.navigationDestination(isPresented: $showIDLogin) {
WithPerceptionTracking {
IDLoginView(
store: store.scope(
state: \.idLoginState,
action: \.idLogin
),
onBack: {
showIDLogin = false
},
showIDLogin: $showIDLogin // Binding
)
.navigationBarHidden(true)
}
}
.navigationDestination(isPresented: $showEmailLogin) {
WithPerceptionTracking {
EMailLoginView(
store: store.scope(
state: \.emailLoginState,
action: \.emailLogin
),
onBack: {
showEmailLogin = false
},
showEmailLogin: $showEmailLogin // Binding
)
.navigationBarHidden(true)
}
}
}
.sheet(isPresented: $showLanguageSettings) {
WithPerceptionTracking {
LanguageSettingsView(isPresented: $showLanguageSettings)
}
}
.webView(
isPresented: $showUserAgreement,
url: APIConfiguration.webURL(for: .userAgreement)
)
.webView(
isPresented: $showPrivacyPolicy,
url: APIConfiguration.webURL(for: .privacyPolicy)
)
//
.onChange(of: store.isAnyLoginCompleted) { completed in
if completed {
onLoginSuccess()
}
}
// showIDLogin
.onChange(of: showIDLogin) { newValue in
if newValue == false && store.isAnyLoginCompleted {
onLoginSuccess()
}
}
// showEmailLogin
.onChange(of: showEmailLogin) { newValue in
if newValue == false && store.isAnyLoginCompleted {
onLoginSuccess()
}
}
}
}
}
//#Preview {
// LoginView(
// store: Store(
// initialState: LoginFeature.State()
// ) {
// LoginFeature()
// },
// onLoginSuccess: {}
// )
//}