wake-ios/wake/View/Owner/UserInfo/UserInfo.swift
2025-08-21 19:22:52 +08:00

237 lines
8.2 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
// 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" : "Whats 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()
}
}