
- 删除CreateFeedView-Analysis.md文档以简化项目结构。 - 新增UserAgreementComponent以处理用户协议的显示和交互。 - 更新多个视图中的onChange逻辑以兼容iOS 17的新API用法,确保代码一致性和可维护性。 - 在Localizable.strings中新增用户协议相关的本地化文本,提升多语言支持。
201 lines
6.6 KiB
Swift
201 lines
6.6 KiB
Swift
import SwiftUI
|
|
import ComposableArchitecture
|
|
import Perception
|
|
|
|
struct LoginView: View {
|
|
let store: StoreOf<LoginFeature>
|
|
let onLoginSuccess: () -> Void
|
|
|
|
// 使用本地@State管理UI状态
|
|
@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
|
|
@State private var isAgreementAccepted: Bool = true // 默认选中
|
|
@State private var showAgreementAlert: Bool = false
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
GeometryReader { geometry in
|
|
ZStack {
|
|
backgroundView
|
|
|
|
VStack(spacing: 0) {
|
|
|
|
Image("top")
|
|
.resizable()
|
|
.aspectRatio(375/400, contentMode: .fit)
|
|
.frame(maxWidth: .infinity)
|
|
|
|
HStack {
|
|
Text(LocalizedString("login.app_title", comment: ""))
|
|
.font(FontManager.adaptedFont(.bayonRegular, designSize: 56, for: geometry.size.width))
|
|
.foregroundColor(.white)
|
|
.padding(.leading, 20)
|
|
Spacer()
|
|
}
|
|
.padding(.bottom, 20) // 距离 top 图片底部的间距
|
|
|
|
Spacer()
|
|
|
|
bottomSection
|
|
}
|
|
|
|
// 语言设置按钮 - 固定在页面右上角
|
|
languageSettingsButton
|
|
.position(x: geometry.size.width - 40, y: 60)
|
|
|
|
APILoadingEffectView()
|
|
}
|
|
}
|
|
.ignoresSafeArea()
|
|
.navigationBarHidden(true)
|
|
.navigationDestination(isPresented: $showIDLogin) {
|
|
IDLoginView(
|
|
store: store.scope(
|
|
state: \.idLoginState,
|
|
action: \.idLogin
|
|
),
|
|
onBack: {
|
|
showIDLogin = false
|
|
},
|
|
showIDLogin: $showIDLogin
|
|
)
|
|
.navigationBarHidden(true)
|
|
}
|
|
.navigationDestination(isPresented: $showEmailLogin) {
|
|
EMailLoginView(
|
|
store: store.scope(
|
|
state: \.emailLoginState,
|
|
action: \.emailLogin
|
|
),
|
|
onBack: {
|
|
showEmailLogin = false
|
|
},
|
|
showEmailLogin: $showEmailLogin
|
|
)
|
|
.navigationBarHidden(true)
|
|
}
|
|
.sheet(isPresented: $showLanguageSettings) {
|
|
LanguageSettingsView(isPresented: $showLanguageSettings)
|
|
}
|
|
.webView(
|
|
isPresented: $showUserAgreement,
|
|
url: APIConfiguration.webURL(for: .userAgreement)
|
|
)
|
|
.webView(
|
|
isPresented: $showPrivacyPolicy,
|
|
url: APIConfiguration.webURL(for: .privacyPolicy)
|
|
)
|
|
.alert(LocalizedString("login.agreement_alert_title", comment: ""), isPresented: $showAgreementAlert) {
|
|
Button(LocalizedString("login.agreement_alert_confirm", comment: "")) { }
|
|
} message: {
|
|
Text(LocalizedString("login.agreement_alert_message", comment: ""))
|
|
}
|
|
.onChange(of: store.isAnyLoginCompleted) { _, isAnyLoginCompleted in
|
|
if isAnyLoginCompleted {
|
|
onLoginSuccess()
|
|
}
|
|
}
|
|
.onChange(of: showIDLogin) { _, showIDLogin in
|
|
if showIDLogin == false && store.isAnyLoginCompleted {
|
|
onLoginSuccess()
|
|
}
|
|
}
|
|
.onChange(of: showEmailLogin) { _, showEmailLogin in
|
|
if showEmailLogin == false && store.isAnyLoginCompleted {
|
|
onLoginSuccess()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 子视图
|
|
|
|
private var backgroundView: some View {
|
|
Image("bg")
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fill)
|
|
.ignoresSafeArea(.all)
|
|
}
|
|
|
|
private var bottomSection: some View {
|
|
VStack(spacing: 20) {
|
|
loginButtons
|
|
userAgreementComponent
|
|
}
|
|
.padding(.horizontal, 28)
|
|
.padding(.bottom, 48)
|
|
}
|
|
|
|
private var loginButtons: some View {
|
|
VStack(spacing: 20) {
|
|
LoginButton(
|
|
iconName: "person.circle",
|
|
iconColor: .blue,
|
|
title: LocalizedString("login.id_login", comment: ""),
|
|
action: {
|
|
if isAgreementAccepted {
|
|
showIDLogin = true
|
|
} else {
|
|
showAgreementAlert = true
|
|
}
|
|
}
|
|
)
|
|
|
|
LoginButton(
|
|
iconName: "envelope",
|
|
iconColor: .green,
|
|
title: LocalizedString("login.email_login", comment: ""),
|
|
action: {
|
|
if isAgreementAccepted {
|
|
showEmailLogin = true
|
|
} else {
|
|
showAgreementAlert = true
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
private var languageSettingsButton: some View {
|
|
Button(action: {
|
|
showLanguageSettings = true
|
|
}) {
|
|
Image(systemName: "globe")
|
|
.font(.system(size: 20))
|
|
.foregroundColor(.white.opacity(0.8))
|
|
}
|
|
}
|
|
|
|
private var userAgreementComponent: some View {
|
|
UserAgreementComponent(
|
|
isAgreed: $isAgreementAccepted,
|
|
onAgreementTap: {
|
|
Task { @MainActor in
|
|
showUserAgreement = true
|
|
}
|
|
},
|
|
onPolicyTap: {
|
|
Task { @MainActor in
|
|
showPrivacyPolicy = true
|
|
}
|
|
}
|
|
)
|
|
.frame(height: 40)
|
|
.padding(.horizontal, -20)
|
|
}
|
|
}
|
|
|
|
//#Preview {
|
|
// LoginView(
|
|
// store: Store(
|
|
// initialState: LoginFeature.State()
|
|
// ) {
|
|
// LoginFeature()
|
|
// },
|
|
// onLoginSuccess: {}
|
|
// )
|
|
//}
|