IceCubesApp/Packages/Account/Sources/Account/Edit/EditAccountViewModel.swift

156 lines
4.8 KiB
Swift
Raw Normal View History

2023-01-10 07:24:05 +00:00
import Models
import Network
import Observation
2024-01-02 20:16:27 +00:00
import PhotosUI
2024-01-06 18:27:26 +00:00
import StatusKit
2024-02-14 11:48:14 +00:00
import SwiftUI
2023-01-10 07:24:05 +00:00
@MainActor
@Observable class EditAccountViewModel {
@Observable class FieldEditViewModel: Identifiable {
2023-02-24 06:55:24 +00:00
let id = UUID().uuidString
var name: String = ""
var value: String = ""
2023-02-26 05:45:57 +00:00
2023-02-24 06:55:24 +00:00
init(name: String, value: String) {
self.name = name
self.value = value
}
}
2023-02-26 05:45:57 +00:00
2023-01-10 07:24:05 +00:00
public var client: Client?
2023-01-17 10:36:01 +00:00
var displayName: String = ""
var note: String = ""
var postPrivacy = Models.Visibility.pub
var isSensitive: Bool = false
var isBot: Bool = false
var isLocked: Bool = false
var isDiscoverable: Bool = false
var fields: [FieldEditViewModel] = []
2024-01-02 20:16:27 +00:00
var avatar: URL?
var header: URL?
2024-02-14 11:48:14 +00:00
2024-01-02 20:16:27 +00:00
var isPhotoPickerPresented: Bool = false {
didSet {
2024-02-14 11:48:14 +00:00
if !isPhotoPickerPresented, mediaPickers.isEmpty {
2024-01-02 20:16:27 +00:00
isChangingAvatar = false
isChangingHeader = false
}
}
}
2024-02-14 11:48:14 +00:00
2024-01-02 20:16:27 +00:00
var isChangingAvatar: Bool = false
var isChangingHeader: Bool = false
2023-01-17 10:36:01 +00:00
var isLoading: Bool = true
var isSaving: Bool = false
var saveError: Bool = false
2024-02-14 11:48:14 +00:00
2024-01-02 20:16:27 +00:00
var mediaPickers: [PhotosPickerItem] = [] {
didSet {
if let item = mediaPickers.first {
Task {
if let data = await getItemImageData(item: item) {
if isChangingAvatar {
_ = await uploadAvatar(data: data)
2024-01-02 20:16:27 +00:00
} else if isChangingHeader {
_ = await uploadHeader(data: data)
2024-01-02 20:16:27 +00:00
}
await fetchAccount()
isChangingAvatar = false
isChangingHeader = false
mediaPickers = []
}
}
}
}
}
2023-01-17 10:36:01 +00:00
init() {}
2023-01-10 07:24:05 +00:00
func fetchAccount() async {
guard let client else { return }
do {
let account: Account = try await client.get(endpoint: Accounts.verifyCredentials)
2023-03-02 19:15:07 +00:00
displayName = account.displayName ?? ""
2023-01-10 07:24:05 +00:00
note = account.source?.note ?? ""
postPrivacy = account.source?.privacy ?? .pub
isSensitive = account.source?.sensitive ?? false
isBot = account.bot
isLocked = account.locked
isDiscoverable = account.discoverable ?? false
2024-01-02 20:16:27 +00:00
avatar = account.avatar
header = account.header
2023-02-26 05:45:57 +00:00
fields = account.source?.fields.map { .init(name: $0.name, value: $0.value.asRawText) } ?? []
2023-01-10 07:24:05 +00:00
withAnimation {
isLoading = false
}
2023-01-17 10:36:01 +00:00
} catch {}
2023-01-10 07:24:05 +00:00
}
2023-01-17 10:36:01 +00:00
2023-01-10 07:24:05 +00:00
func save() async {
isSaving = true
do {
2023-02-24 06:55:24 +00:00
let data = UpdateCredentialsData(displayName: displayName,
note: note,
source: .init(privacy: postPrivacy, sensitive: isSensitive),
bot: isBot,
locked: isLocked,
discoverable: isDiscoverable,
2023-02-26 05:45:57 +00:00
fieldsAttributes: fields.map { .init(name: $0.name, value: $0.value) })
2023-02-24 06:55:24 +00:00
let response = try await client?.patch(endpoint: Accounts.updateCredentials(json: data))
2023-01-10 07:24:05 +00:00
if response?.statusCode != 200 {
saveError = true
}
isSaving = false
} catch {
isSaving = false
saveError = true
}
}
2024-02-14 11:48:14 +00:00
2024-01-02 20:16:27 +00:00
private func uploadHeader(data: Data) async -> Bool {
guard let client else { return false }
do {
let response = try await client.mediaUpload(endpoint: Accounts.updateCredentialsMedia,
2024-02-14 11:48:14 +00:00
version: .v1,
method: "PATCH",
mimeType: "image/jpeg",
filename: "header",
data: data)
2024-01-02 20:16:27 +00:00
return response?.statusCode == 200
} catch {
return false
}
}
2024-02-14 11:48:14 +00:00
2024-01-02 20:16:27 +00:00
private func uploadAvatar(data: Data) async -> Bool {
guard let client else { return false }
do {
let response = try await client.mediaUpload(endpoint: Accounts.updateCredentialsMedia,
2024-02-14 11:48:14 +00:00
version: .v1,
method: "PATCH",
mimeType: "image/jpeg",
filename: "avatar",
data: data)
2024-01-02 20:16:27 +00:00
return response?.statusCode == 200
} catch {
return false
}
}
2024-02-14 11:48:14 +00:00
2024-01-02 20:16:27 +00:00
private func getItemImageData(item: PhotosPickerItem) async -> Data? {
2024-01-06 17:43:26 +00:00
guard let imageFile = try? await item.loadTransferable(type: StatusEditor.ImageFileTranseferable.self) else { return nil }
2024-01-02 20:16:27 +00:00
2024-01-06 17:43:26 +00:00
let compressor = StatusEditor.Compressor()
2024-01-02 20:16:27 +00:00
guard let compressedData = await compressor.compressImageFrom(url: imageFile.url),
2024-02-14 11:48:14 +00:00
let image = UIImage(data: compressedData),
let uploadData = try? await compressor.compressImageForUpload(image)
2024-01-02 20:16:27 +00:00
else { return nil }
2024-02-14 11:48:14 +00:00
2024-01-02 20:16:27 +00:00
return uploadData
}
2023-01-10 07:24:05 +00:00
}