photo in edit profile
This commit is contained in:
parent
aa157031a1
commit
0ea5fbf996
@ -5,6 +5,7 @@ struct ProfileDataPayload: Decodable {
|
|||||||
let login: String
|
let login: String
|
||||||
let fullName: String?
|
let fullName: String?
|
||||||
let bio: String?
|
let bio: String?
|
||||||
|
let avatars: Avatars?
|
||||||
let balances: [WalletBalancePayload]
|
let balances: [WalletBalancePayload]
|
||||||
let createdAt: Date?
|
let createdAt: Date?
|
||||||
let stories: [JSONValue]
|
let stories: [JSONValue]
|
||||||
@ -15,6 +16,7 @@ struct ProfileDataPayload: Decodable {
|
|||||||
case login
|
case login
|
||||||
case fullName
|
case fullName
|
||||||
case bio
|
case bio
|
||||||
|
case avatars
|
||||||
case balances
|
case balances
|
||||||
case createdAt
|
case createdAt
|
||||||
case stories
|
case stories
|
||||||
@ -27,6 +29,7 @@ struct ProfileDataPayload: Decodable {
|
|||||||
self.login = try container.decode(String.self, forKey: .login)
|
self.login = try container.decode(String.self, forKey: .login)
|
||||||
self.fullName = try container.decodeIfPresent(String.self, forKey: .fullName)
|
self.fullName = try container.decodeIfPresent(String.self, forKey: .fullName)
|
||||||
self.bio = try container.decodeIfPresent(String.self, forKey: .bio)
|
self.bio = try container.decodeIfPresent(String.self, forKey: .bio)
|
||||||
|
self.avatars = try container.decodeIfPresent(Avatars.self, forKey: .avatars)
|
||||||
self.balances = try container.decodeIfPresent([WalletBalancePayload].self, forKey: .balances) ?? []
|
self.balances = try container.decodeIfPresent([WalletBalancePayload].self, forKey: .balances) ?? []
|
||||||
self.createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt)
|
self.createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt)
|
||||||
self.stories = try container.decodeIfPresent([JSONValue].self, forKey: .stories) ?? []
|
self.stories = try container.decodeIfPresent([JSONValue].self, forKey: .stories) ?? []
|
||||||
@ -34,6 +37,19 @@ struct ProfileDataPayload: Decodable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//struct AvatarInfo: Decodable {
|
||||||
|
// let fileId: String
|
||||||
|
// let mime: String?
|
||||||
|
// let size: Int?
|
||||||
|
// let width: Int?
|
||||||
|
// let height: Int?
|
||||||
|
// let createdAt: Date?
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//struct Avatars: Decodable {
|
||||||
|
// let current: AvatarInfo?
|
||||||
|
//}
|
||||||
|
|
||||||
struct WalletBalancePayload: Decodable {
|
struct WalletBalancePayload: Decodable {
|
||||||
let currency: String
|
let currency: String
|
||||||
let balance: Decimal
|
let balance: Decimal
|
||||||
|
|||||||
@ -1,15 +1,25 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct EditProfileView: View {
|
struct EditProfileView: View {
|
||||||
|
// State for form fields
|
||||||
@State private var displayName = ""
|
@State private var displayName = ""
|
||||||
@State private var description = ""
|
@State private var description = ""
|
||||||
|
|
||||||
|
// State for profile data and avatar
|
||||||
|
@State private var profile: ProfileDataPayload?
|
||||||
@State private var avatarImage: UIImage?
|
@State private var avatarImage: UIImage?
|
||||||
@State private var showImagePicker = false
|
@State private var showImagePicker = false
|
||||||
|
|
||||||
|
// State for loading and errors
|
||||||
|
@State private var isLoading = false
|
||||||
|
@State private var alertMessage: String?
|
||||||
|
@State private var showAlert = false
|
||||||
|
|
||||||
|
private let profileService = ProfileService()
|
||||||
private let descriptionLimit = 1024
|
private let descriptionLimit = 1024
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
ZStack {
|
||||||
Form {
|
Form {
|
||||||
Section {
|
Section {
|
||||||
HStack {
|
HStack {
|
||||||
@ -21,16 +31,19 @@ struct EditProfileView: View {
|
|||||||
.scaledToFill()
|
.scaledToFill()
|
||||||
.frame(width: 120, height: 120)
|
.frame(width: 120, height: 120)
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
} else {
|
} else if let profile = profile,
|
||||||
Circle()
|
let fileId = profile.avatars?.current?.fileId,
|
||||||
.fill(Color.secondary.opacity(0.2))
|
let url = avatarUrl(for: profile, fileId: fileId) {
|
||||||
.frame(width: 120, height: 120)
|
CachedAvatarView(url: url, fileId: fileId, userId: profile.userId.uuidString) {
|
||||||
.overlay(
|
avatarPlaceholder
|
||||||
Image(systemName: "person.fill")
|
|
||||||
.font(.system(size: 60))
|
|
||||||
.foregroundColor(.gray)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
.aspectRatio(contentMode: .fill)
|
||||||
|
.frame(width: 120, height: 120)
|
||||||
|
.clipShape(Circle())
|
||||||
|
} else {
|
||||||
|
avatarPlaceholder
|
||||||
|
}
|
||||||
|
|
||||||
Button("Изменить фото") {
|
Button("Изменить фото") {
|
||||||
showImagePicker = true
|
showImagePicker = true
|
||||||
}
|
}
|
||||||
@ -73,9 +86,60 @@ struct EditProfileView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.navigationTitle("Редактировать профиль")
|
.navigationTitle("Редактировать профиль")
|
||||||
|
.onAppear(perform: loadProfile)
|
||||||
.sheet(isPresented: $showImagePicker) {
|
.sheet(isPresented: $showImagePicker) {
|
||||||
ImagePicker(image: $avatarImage)
|
ImagePicker(image: $avatarImage)
|
||||||
}
|
}
|
||||||
|
.alert("Ошибка", isPresented: $showAlert, presenting: alertMessage) { _ in
|
||||||
|
Button("OK") {}
|
||||||
|
} message: { message in
|
||||||
|
Text(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
if isLoading {
|
||||||
|
Color.black.opacity(0.4).ignoresSafeArea()
|
||||||
|
ProgressView("Загрузка...")
|
||||||
|
.padding()
|
||||||
|
.background(Color.secondary.colorInvert())
|
||||||
|
.cornerRadius(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var avatarPlaceholder: some View {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.secondary.opacity(0.2))
|
||||||
|
.frame(width: 120, height: 120)
|
||||||
|
.overlay(
|
||||||
|
Image(systemName: "person.fill")
|
||||||
|
.font(.system(size: 60))
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func avatarUrl(for profile: ProfileDataPayload, fileId: String) -> URL? {
|
||||||
|
return URL(string: "\(AppConfig.API_SERVER)/v1/storage/download/avatar/\(profile.userId)?file_id=\(fileId)")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadProfile() {
|
||||||
|
isLoading = true
|
||||||
|
Task {
|
||||||
|
do {
|
||||||
|
let profile = try await profileService.fetchMyProfile()
|
||||||
|
await MainActor.run {
|
||||||
|
self.profile = profile
|
||||||
|
self.displayName = profile.fullName ?? ""
|
||||||
|
self.description = profile.bio ?? ""
|
||||||
|
self.isLoading = false
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
await MainActor.run {
|
||||||
|
self.alertMessage = error.localizedDescription
|
||||||
|
self.showAlert = true
|
||||||
|
self.isLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user