From 7ef4b383fbf4bab2744d19df7ca3d6abef5a869c Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Tue, 5 Apr 2022 14:51:06 -0700 Subject: [PATCH] add ability to delete labels from ios --- .../App/Views/Profile/LabelsView.swift | 49 +++++++++++++++-- .../Mutations/RemoveLabelPublisher.swift | 53 +++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 apple/OmnivoreKit/Sources/Services/DataService/Mutations/RemoveLabelPublisher.swift diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/LabelsView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/LabelsView.swift index 9853cb993..852b64e8c 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/LabelsView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/LabelsView.swift @@ -46,20 +46,53 @@ final class LabelsViewModel: ObservableObject { ) .store(in: &subscriptions) } + + func deleteLabel(dataService: DataService, labelID: String) { + isLoading = true + + dataService.removeLabelPublisher(labelID: labelID).sink( + receiveCompletion: { [weak self] _ in + self?.isLoading = false + }, + receiveValue: { [weak self] _ in + self?.isLoading = false + self?.labels.removeAll { $0.id == labelID } + } + ) + .store(in: &subscriptions) + } } struct LabelsView: View { @EnvironmentObject var dataService: DataService @StateObject var viewModel = LabelsViewModel() + @State private var showDeleteConfirmation = false + @State private var labelToRemoveID: String? let footerText = "Use labels to create curated collections of links." var body: some View { Group { #if os(iOS) - Form { - innerBody + if #available(iOS 15.0, *) { + Form { + innerBody + .alert("Are you sure you want to delete this label?", isPresented: $showDeleteConfirmation) { + Button("Remove Link", role: .destructive) { + if let labelID = labelToRemoveID { + withAnimation { + viewModel.deleteLabel(dataService: dataService, labelID: labelID) + } + } + self.labelToRemoveID = nil + } + Button("Cancel", role: .cancel) { self.labelToRemoveID = nil } + } + } + } else { + Form { innerBody } } + #elseif os(macOS) List { innerBody @@ -89,7 +122,17 @@ struct LabelsView: View { if !viewModel.labels.isEmpty { Section(header: Text("Labels")) { ForEach(viewModel.labels, id: \.id) { label in - Text(label.name) + HStack { + Text(label.name) + Spacer() + Button( + action: { + labelToRemoveID = label.id + showDeleteConfirmation = true + }, + label: { Image(systemName: "trash") } + ) + } } } } diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/RemoveLabelPublisher.swift b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/RemoveLabelPublisher.swift new file mode 100644 index 000000000..134954a4f --- /dev/null +++ b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/RemoveLabelPublisher.swift @@ -0,0 +1,53 @@ +import Combine +import Foundation +import Models +import SwiftGraphQL + +public extension DataService { + func removeLabelPublisher(labelID: String) -> AnyPublisher { + enum MutationResult { + case success(labelID: String) + case error(errorCode: Enums.DeleteLabelErrorCode) + } + + let selection = Selection { + try $0.on( + deleteLabelSuccess: .init { + .success(labelID: try $0.label(selection: Selection.Label { try $0.id() })) + }, + deleteLabelError: .init { .error(errorCode: try $0.errorCodes().first ?? .badRequest) } + ) + } + + let mutation = Selection.Mutation { + try $0.deleteLabel(id: labelID, selection: selection) + } + + let path = appEnvironment.graphqlPath + let headers = networker.defaultHeaders + + return Deferred { + Future { promise in + send(mutation, to: path, headers: headers) { result in + switch result { + case let .success(payload): + if payload.errors != nil { + promise(.failure(.message(messageText: "Error removing label"))) + } + + switch payload.data { + case .success: + promise(.success(true)) + case .error: + promise(.failure(.message(messageText: "Error removing label"))) + } + case .failure: + promise(.failure(.message(messageText: "Error removing label"))) + } + } + } + } + .receive(on: DispatchQueue.main) + .eraseToAnyPublisher() + } +}