add delete contact
This commit is contained in:
parent
a1446ec8bf
commit
bb08452ff9
@ -40,6 +40,10 @@ private struct ContactCreateRequestPayload: Encodable {
|
||||
let customName: String?
|
||||
}
|
||||
|
||||
private struct ContactDeleteRequestPayload: Encodable {
|
||||
let userId: UUID
|
||||
}
|
||||
|
||||
final class ContactsService {
|
||||
private let client: NetworkClient
|
||||
private let decoder: JSONDecoder
|
||||
@ -159,6 +163,58 @@ final class ContactsService {
|
||||
}
|
||||
}
|
||||
|
||||
func removeContact(userId: UUID, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
let request = ContactDeleteRequestPayload(userId: userId)
|
||||
|
||||
guard let body = try? encoder.encode(request) else {
|
||||
let message = NSLocalizedString("Не удалось подготовить данные запроса.", comment: "Contacts service encoding error")
|
||||
completion(.failure(ContactsServiceError.encoding(message)))
|
||||
return
|
||||
}
|
||||
|
||||
client.request(
|
||||
path: "/v1/user/contact/remove",
|
||||
method: .delete,
|
||||
body: body,
|
||||
requiresAuth: true
|
||||
) { [decoder] result in
|
||||
switch result {
|
||||
case .success(let response):
|
||||
do {
|
||||
let apiResponse = try decoder.decode(APIResponse<MessagePayload>.self, from: response.data)
|
||||
guard apiResponse.status == "fine" else {
|
||||
let message = apiResponse.detail ?? NSLocalizedString("Не удалось удалить контакт.", comment: "Contacts service delete unexpected status")
|
||||
completion(.failure(ContactsServiceError.unexpectedStatus(message)))
|
||||
return
|
||||
}
|
||||
completion(.success(()))
|
||||
} catch {
|
||||
let debugMessage = Self.describeDecodingError(error: error, data: response.data)
|
||||
if AppConfig.DEBUG {
|
||||
print("[ContactsService] decode contact delete failed: \(debugMessage)")
|
||||
}
|
||||
completion(.failure(ContactsServiceError.decoding(debugDescription: debugMessage)))
|
||||
}
|
||||
case .failure(let error):
|
||||
if case let NetworkError.server(_, data) = error,
|
||||
let data,
|
||||
let message = Self.errorMessage(from: data) {
|
||||
completion(.failure(ContactsServiceError.unexpectedStatus(message)))
|
||||
return
|
||||
}
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func removeContact(userId: UUID) async throws {
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
removeContact(userId: userId) { result in
|
||||
continuation.resume(with: result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static func decodeDate(from decoder: Decoder) throws -> Date {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let string = try container.decode(String.self)
|
||||
|
||||
@ -938,6 +938,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Контакт \"%1$@\" будет удалён из списка." : {
|
||||
"comment" : "Contact delete confirmation message"
|
||||
},
|
||||
"Контактов пока нет" : {
|
||||
"comment" : "Contacts empty state title"
|
||||
},
|
||||
@ -1441,6 +1444,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Не удалось определить контакт." : {
|
||||
"comment" : "Contact delete invalid user id error"
|
||||
},
|
||||
"Не удалось определить пользователя для блокировки." : {
|
||||
"comment" : "Message profile missing user id error"
|
||||
},
|
||||
@ -1484,6 +1490,9 @@
|
||||
"Не удалось сохранить изменения профиля." : {
|
||||
"comment" : "Profile update unexpected status"
|
||||
},
|
||||
"Не удалось удалить контакт." : {
|
||||
"comment" : "Contacts service delete unexpected status"
|
||||
},
|
||||
"Не удалось удалить пользователя из списка." : {
|
||||
"comment" : "Blocked users delete unexpected status"
|
||||
},
|
||||
@ -2998,6 +3007,7 @@
|
||||
},
|
||||
"Удаление контакта появится позже." : {
|
||||
"comment" : "Contact edit delete placeholder message",
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
@ -3007,12 +3017,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Удалить" : {
|
||||
"comment" : "Contact delete confirm action"
|
||||
},
|
||||
"Удалить из заблокированных?" : {
|
||||
"comment" : "Unblock confirmation title"
|
||||
},
|
||||
"Удалить контакт" : {
|
||||
"comment" : "Contact edit delete action\nContacts context action delete"
|
||||
},
|
||||
"Удалить контакт?" : {
|
||||
"comment" : "Contact delete confirmation title"
|
||||
},
|
||||
"Удалить фото" : {
|
||||
"comment" : "Avatar delete"
|
||||
},
|
||||
@ -3026,6 +3042,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Удаляем..." : {
|
||||
"comment" : "Contact delete in progress"
|
||||
},
|
||||
"Удалять аккаунт через %lld дн." : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
|
||||
@ -48,7 +48,9 @@ struct MessageProfileView: View {
|
||||
if canEditContact {
|
||||
if let profile = currentChatProfile {
|
||||
NavigationLink {
|
||||
ContactEditView(contact: ContactEditInfo(profile: profile))
|
||||
ContactEditView(contact: ContactEditInfo(profile: profile)) {
|
||||
handleContactDeleted()
|
||||
}
|
||||
} label: {
|
||||
Text(NSLocalizedString("Изменить", comment: "Message profile edit contact button"))
|
||||
}
|
||||
@ -596,6 +598,37 @@ struct MessageProfileView: View {
|
||||
chatProfile = updatedProfile
|
||||
}
|
||||
|
||||
private func handleContactDeleted() {
|
||||
guard let profile = currentChatProfile else { return }
|
||||
|
||||
let existingRelationship = profile.relationship
|
||||
let updatedRelationship = RelationshipStatus(
|
||||
isTargetInContactsOfCurrentUser: false,
|
||||
isCurrentUserInContactsOfTarget: existingRelationship?.isCurrentUserInContactsOfTarget ?? false,
|
||||
isTargetUserBlockedByCurrentUser: existingRelationship?.isTargetUserBlockedByCurrentUser ?? false,
|
||||
isCurrentUserInBlacklistOfTarget: existingRelationship?.isCurrentUserInBlacklistOfTarget ?? false
|
||||
)
|
||||
|
||||
let updatedProfile = ChatProfile(
|
||||
userId: profile.userId,
|
||||
login: profile.login,
|
||||
fullName: profile.fullName,
|
||||
customName: nil,
|
||||
bio: profile.bio,
|
||||
lastSeen: profile.lastSeen,
|
||||
createdAt: profile.createdAt,
|
||||
avatars: profile.avatars,
|
||||
stories: profile.stories,
|
||||
permissions: profile.permissions,
|
||||
profilePermissions: profile.profilePermissions,
|
||||
relationship: updatedRelationship,
|
||||
rating: profile.rating,
|
||||
isOfficial: profile.isOfficial
|
||||
)
|
||||
|
||||
chatProfile = updatedProfile
|
||||
}
|
||||
|
||||
private func handleEditContactTap() {
|
||||
showPlaceholderAction(
|
||||
title: NSLocalizedString("Ошибка", comment: "Common error title"),
|
||||
|
||||
@ -55,12 +55,19 @@ struct ContactEditInfo {
|
||||
|
||||
struct ContactEditView: View {
|
||||
let contact: ContactEditInfo
|
||||
let onContactDeleted: (() -> Void)?
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
private let contactsService = ContactsService()
|
||||
|
||||
@State private var displayName: String
|
||||
@State private var activeAlert: ContactEditAlert?
|
||||
@State private var isDeleting = false
|
||||
@State private var showDeleteConfirmation = false
|
||||
|
||||
init(contact: ContactEditInfo) {
|
||||
init(contact: ContactEditInfo, onContactDeleted: (() -> Void)? = nil) {
|
||||
self.contact = contact
|
||||
self.onContactDeleted = onContactDeleted
|
||||
let initialName = contact.preferredName
|
||||
_displayName = State(initialValue: initialName)
|
||||
}
|
||||
@ -77,9 +84,9 @@ struct ContactEditView: View {
|
||||
Button(role: .destructive) {
|
||||
handleDeleteTap()
|
||||
} label: {
|
||||
Text(NSLocalizedString("Удалить контакт", comment: "Contact edit delete action"))
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
deleteButtonLabel
|
||||
}
|
||||
.disabled(isDeleting)
|
||||
}
|
||||
}
|
||||
.navigationTitle(NSLocalizedString("Контакт", comment: "Contact edit title"))
|
||||
@ -99,6 +106,37 @@ struct ContactEditView: View {
|
||||
dismissButton: .default(Text(NSLocalizedString("Понятно", comment: "Placeholder alert dismiss")))
|
||||
)
|
||||
}
|
||||
.confirmationDialog(
|
||||
NSLocalizedString("Удалить контакт?", comment: "Contact delete confirmation title"),
|
||||
isPresented: $showDeleteConfirmation,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button(NSLocalizedString("Удалить", comment: "Contact delete confirm action"), role: .destructive) {
|
||||
confirmDelete()
|
||||
}
|
||||
Button(NSLocalizedString("Отмена", comment: "Common cancel"), role: .cancel) {
|
||||
showDeleteConfirmation = false
|
||||
}
|
||||
} message: {
|
||||
Text(String(
|
||||
format: NSLocalizedString("Контакт \"%1$@\" будет удалён из списка.", comment: "Contact delete confirmation message"),
|
||||
contact.preferredName
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var deleteButtonLabel: some View {
|
||||
if isDeleting {
|
||||
HStack(spacing: 8) {
|
||||
ProgressView()
|
||||
Text(NSLocalizedString("Удаляем...", comment: "Contact delete in progress"))
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
} else {
|
||||
Text(NSLocalizedString("Удалить контакт", comment: "Contact edit delete action"))
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
}
|
||||
}
|
||||
|
||||
private var avatarSection: some View {
|
||||
@ -185,10 +223,41 @@ struct ContactEditView: View {
|
||||
}
|
||||
|
||||
private func handleDeleteTap() {
|
||||
activeAlert = ContactEditAlert(
|
||||
title: NSLocalizedString("Скоро", comment: "Common soon title"),
|
||||
message: NSLocalizedString("Удаление контакта появится позже.", comment: "Contact edit delete placeholder message")
|
||||
)
|
||||
guard !isDeleting else { return }
|
||||
showDeleteConfirmation = true
|
||||
}
|
||||
|
||||
private func confirmDelete() {
|
||||
guard !isDeleting else { return }
|
||||
guard let userId = UUID(uuidString: contact.userId) else {
|
||||
activeAlert = ContactEditAlert(
|
||||
title: NSLocalizedString("Ошибка", comment: "Common error title"),
|
||||
message: NSLocalizedString("Не удалось определить контакт.", comment: "Contact delete invalid user id error")
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
isDeleting = true
|
||||
showDeleteConfirmation = false
|
||||
|
||||
Task {
|
||||
do {
|
||||
try await contactsService.removeContact(userId: userId)
|
||||
await MainActor.run {
|
||||
isDeleting = false
|
||||
onContactDeleted?()
|
||||
dismiss()
|
||||
}
|
||||
} catch {
|
||||
await MainActor.run {
|
||||
isDeleting = false
|
||||
activeAlert = ContactEditAlert(
|
||||
title: NSLocalizedString("Ошибка", comment: "Common error title"),
|
||||
message: error.localizedDescription
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user