120 行
3.6 KiB
Swift
120 行
3.6 KiB
Swift
|
|
import SwiftUI
|
||
|
|
import XuqmSDK
|
||
|
|
|
||
|
|
@MainActor
|
||
|
|
final class ProfileViewModel: ObservableObject {
|
||
|
|
@Published var profile: UserProfile?
|
||
|
|
@Published var isLoading = false
|
||
|
|
@Published var errorMessage: String?
|
||
|
|
@Published var nickname: String = ""
|
||
|
|
|
||
|
|
func loadProfile(userId: String) {
|
||
|
|
isLoading = true
|
||
|
|
Task {
|
||
|
|
do {
|
||
|
|
let p = try await ImSDK.shared.getProfile(userId: userId)
|
||
|
|
profile = p
|
||
|
|
nickname = p.nickname ?? userId
|
||
|
|
isLoading = false
|
||
|
|
} catch {
|
||
|
|
errorMessage = error.localizedDescription
|
||
|
|
isLoading = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func saveProfile(userId: String) {
|
||
|
|
isLoading = true
|
||
|
|
Task {
|
||
|
|
do {
|
||
|
|
let p = try await ImSDK.shared.updateProfile(userId: userId, nickname: nickname)
|
||
|
|
profile = p
|
||
|
|
isLoading = false
|
||
|
|
} catch {
|
||
|
|
errorMessage = error.localizedDescription
|
||
|
|
isLoading = false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
struct ProfileView: View {
|
||
|
|
@ObservedObject var authViewModel: AuthViewModel
|
||
|
|
@StateObject private var viewModel = ProfileViewModel()
|
||
|
|
|
||
|
|
var body: some View {
|
||
|
|
VStack(spacing: 20) {
|
||
|
|
Spacer().frame(height: 40)
|
||
|
|
|
||
|
|
ZStack {
|
||
|
|
Circle()
|
||
|
|
.fill(Color.accentColor.opacity(0.15))
|
||
|
|
.frame(width: 80, height: 80)
|
||
|
|
Text(String(viewModel.nickname.prefix(1).uppercased()))
|
||
|
|
.font(.largeTitle)
|
||
|
|
.foregroundStyle(Color.accentColor)
|
||
|
|
}
|
||
|
|
|
||
|
|
Text(authViewModel.currentUserId)
|
||
|
|
.font(.caption)
|
||
|
|
.foregroundStyle(.secondary)
|
||
|
|
|
||
|
|
Divider()
|
||
|
|
.padding(.horizontal)
|
||
|
|
|
||
|
|
VStack(alignment: .leading, spacing: 8) {
|
||
|
|
Text("昵称")
|
||
|
|
.font(.caption)
|
||
|
|
.foregroundStyle(.secondary)
|
||
|
|
TextField("输入昵称", text: $viewModel.nickname)
|
||
|
|
.textFieldStyle(.roundedBorder)
|
||
|
|
}
|
||
|
|
.padding(.horizontal)
|
||
|
|
|
||
|
|
if let error = viewModel.errorMessage {
|
||
|
|
Text(error)
|
||
|
|
.font(.caption)
|
||
|
|
.foregroundStyle(.red)
|
||
|
|
}
|
||
|
|
|
||
|
|
Button {
|
||
|
|
viewModel.saveProfile(userId: authViewModel.currentUserId)
|
||
|
|
} label: {
|
||
|
|
HStack {
|
||
|
|
if viewModel.isLoading {
|
||
|
|
ProgressView()
|
||
|
|
}
|
||
|
|
Text("保存")
|
||
|
|
}
|
||
|
|
.frame(maxWidth: .infinity)
|
||
|
|
.padding()
|
||
|
|
.background(Color.accentColor)
|
||
|
|
.foregroundStyle(.white)
|
||
|
|
.clipShape(RoundedRectangle(cornerRadius: 12))
|
||
|
|
}
|
||
|
|
.disabled(viewModel.isLoading || viewModel.nickname.isEmpty)
|
||
|
|
.padding(.horizontal)
|
||
|
|
|
||
|
|
Spacer()
|
||
|
|
|
||
|
|
Button {
|
||
|
|
authViewModel.logout()
|
||
|
|
} label: {
|
||
|
|
Text("退出登录")
|
||
|
|
.frame(maxWidth: .infinity)
|
||
|
|
.padding()
|
||
|
|
.background(Color.red.opacity(0.1))
|
||
|
|
.foregroundStyle(.red)
|
||
|
|
.clipShape(RoundedRectangle(cornerRadius: 12))
|
||
|
|
}
|
||
|
|
.padding(.horizontal)
|
||
|
|
}
|
||
|
|
.padding()
|
||
|
|
.onAppear {
|
||
|
|
if !authViewModel.currentUserId.isEmpty {
|
||
|
|
viewModel.loadProfile(userId: authViewModel.currentUserId)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|