XuqmGroup-iOSSDK/XuqmDemo/Sources/Views/ProfileView.swift
XuqmGroup e7067d03cb feat(sdk): 更新 SDK 设计文档和 API 重构
- 添加 expiresAt 和 refreshUserSig 参数支持自动续签
- 修改 PushSDK 初始化方式,自动完成设备注册和厂商初始化
- 调整过期续签策略,从提前 15 分钟改为提前 5 分钟触发
- 重构 RN SDK 文档结构,简化安装和使用方式
- 更新统一登录流程,支持 profile 信息传递
- 添加 IM 数据库自动隔离功能
- 修复 Android 群消息聚合问题
- 补充自动化测试验证和错误处理机制
2026-05-01 21:27:39 +08:00

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)
}
}
}
}