import SwiftUI // MARK: - UIApplication Extension for Hiding Keyboard #if canImport(UIKit) extension View { func hideKeyboard() { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } } #endif struct UserInfo: View { @Environment(\.dismiss) private var dismiss @State private var keyboardHeight: CGFloat = 0 @State private var isKeyboardVisible = false // Sample user data - replace with your actual data model @State private var userName = "" @State private var notificationsEnabled = true @State private var darkModeEnabled = false @State private var showLogoutAlert = false @State private var avatarImage: UIImage? = nil @State private var uploadedFileId: String? = nil @State private var showUsername = false private struct MessageView: View { let isKeyboardVisible: Bool private var singleLineText: some View { Text("Choose a photo as your avatar, and we'll generate a video mystery box for you.") .font(Typography.font(for: .caption)) .foregroundColor(.black) .lineLimit(1) .truncationMode(.tail) .padding(3) } private var multiLineText: some View { Text("Choose a photo as your avatar, and we'll generate a video mystery box for you.") .font(Typography.font(for: .caption)) .foregroundColor(.black) .fixedSize(horizontal: false, vertical: true) .padding(3) } private var background: some View { LinearGradient( gradient: Gradient(colors: [ Color(red: 1.0, green: 0.97, blue: 0.87), .white, Color(red: 1.0, green: 0.97, blue: 0.84) ]), startPoint: .topLeading, endPoint: .bottomTrailing ) } var body: some View { HStack { if isKeyboardVisible { singleLineText .transition(.asymmetric( insertion: .opacity.combined(with: .scale(scale: 0.95)), removal: .opacity.combined(with: .scale(scale: 1.05)) )) } else { multiLineText .transition(.asymmetric( insertion: .opacity.combined(with: .scale(scale: 1.05)), removal: .opacity.combined(with: .scale(scale: 0.95)) )) } } .background(background) .animation(.spring(response: 0.3, dampingFraction: 1), value: isKeyboardVisible) } } var body: some View { VStack(spacing: 0) { HStack { ReturnButton { print("返回") } Spacer() Text("Complete Your Profile") .font(Typography.font(for: .title2, family: .quicksandBold)) .foregroundColor(.themeTextMessageMain) Spacer() } .padding() // 文描述 MessageView(isKeyboardVisible: isKeyboardVisible).padding(.bottom, 6) if !isKeyboardVisible { Spacer() } VStack(spacing: 20) { // Title Text(showUsername ? "Add Your Avatar" : "What‘s Your Name?") .font(Typography.font(for: .body, family: .quicksandBold)) .frame(maxWidth: .infinity, alignment: .center) // Avatar ZStack { AvatarPicker( selectedImage: $avatarImage, showUsername: $showUsername, isKeyboardVisible: $isKeyboardVisible, onFileUploaded: { fileId in // 保存上传后的文件ID print("Uploaded file ID: \(fileId)") uploadedFileId = fileId } ) } .padding(.top, 20) if !showUsername { Button(action: { // Action for second button }) { Text("Take a Photo") .font(Typography.font(for: .subtitle, family: .inter)) .fontWeight(.regular) .frame(maxWidth: .infinity) .padding() .foregroundColor(.black) .background( RoundedRectangle(cornerRadius: 16) .fill(Color.themePrimaryLight) ) } } if showUsername { TextField("Username", text: $userName) .font(Typography.font(for: .subtitle, family: .inter)) .multilineTextAlignment(.center) .frame(maxWidth: .infinity) .padding() .foregroundColor(.black) .background( RoundedRectangle(cornerRadius: 16) .fill(Color.themePrimaryLight) ) } } .padding() .background(Color(.white)) .cornerRadius(20) if !isKeyboardVisible { Spacer() } Button(action: { if showUsername { print("调接口将头像和username传到后端", uploadedFileId ?? "") // 调接口将头像和username传到后端 UserService.shared.updateUsername(userName, userId: uploadedFileId ?? "") { result in switch result { case .success(let response): print("Username updated: \(response.message ?? "")") case .failure(let error): print("Error updating username: \(error.localizedDescription)") } } } else { showUsername = true } }) { Text(showUsername ? "Open" : "Continue") .font(Typography.font(for: .body)) .fontWeight(.bold) .frame(maxWidth: .infinity) .padding(16) .foregroundColor(.black) .background( RoundedRectangle(cornerRadius: 25) .fill(Color.themePrimary) ) } .padding() } .padding() .navigationBarTitleDisplayMode(.inline) .background(Color(red: 0.98, green: 0.98, blue: 0.98)) // #FAFAFA .onTapGesture { hideKeyboard() } .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { _ in withAnimation { isKeyboardVisible = true } } .onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in withAnimation { isKeyboardVisible = false } } } } // MARK: - Settings Row View struct SettingsRow: View { let icon: String let title: String let color: Color var body: some View { HStack { Image(systemName: icon) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 20, height: 20) .padding(6) .background(color.opacity(0.1)) .foregroundColor(color) .cornerRadius(6) Text(title) .padding(.leading, 5) } .padding(.vertical, 4) } } // MARK: - Preview struct UserInfo_Previews: PreviewProvider { static var previews: some View { UserInfo() } }