diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupView.swift index 3367c28ca..7687229f1 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupView.swift @@ -5,7 +5,9 @@ import Views @MainActor final class RecommendationsGroupViewModel: ObservableObject { @Published var isLoading = false + @Published var isLeaving = false @Published var networkError = false + @Published var showLeaveGroup = false @Published var recommendationGroup: InternalRecommendationGroup init(recommendationGroup: InternalRecommendationGroup) { @@ -17,6 +19,15 @@ import Views !recommendationGroup.admins.contains(where: { member.id == $0.id }) } } + + func leaveGroup(dataService: DataService) async -> Bool { + isLeaving = true + try? await dataService.leaveGroup(groupID: recommendationGroup.id) + + isLeaving = false + Snackbar.show(message: "You have left the group.") + return true + } } private struct SmallUserCard: View { @@ -68,6 +79,8 @@ private struct SmallUserCard: View { } struct RecommendationGroupView: View { + @Environment(\.dismiss) private var dismiss + @EnvironmentObject var dataService: DataService @StateObject var viewModel: RecommendationsGroupViewModel @@ -128,6 +141,16 @@ struct RecommendationGroupView: View { } } + private var leaveSection: some View { + if viewModel.isLeaving { + return AnyView(ProgressView()) + } + return AnyView(Button(action: { + viewModel.showLeaveGroup = true + }, label: { Text("Leave Group") }) + .accentColor(.red)) + } + private var innerBody: some View { Group { Section("Name") { @@ -155,6 +178,22 @@ struct RecommendationGroupView: View { adminsSection membersSection + + leaveSection + } + .alert(isPresented: $viewModel.showLeaveGroup) { + Alert( + title: Text("Are you sure you want to leave this group? No data will be deleted, but you will stop receiving recommendations from the group."), + primaryButton: .destructive(Text("Leave Group")) { + Task { + let success = await viewModel.leaveGroup(dataService: dataService) + if success { + dismiss() + } + } + }, + secondaryButton: .cancel() + ) } .navigationTitle(viewModel.recommendationGroup.name) } diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/LeaveGroup.swift b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/LeaveGroup.swift new file mode 100644 index 000000000..b772a8119 --- /dev/null +++ b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/LeaveGroup.swift @@ -0,0 +1,49 @@ +import CoreData +import Foundation +import Models +import SwiftGraphQL + +public extension DataService { + func leaveGroup(groupID _: String) async throws { +// enum MutationResult { +// case saved(success: Bool) +// case error(errorMessage: String) +// } +// +// let selection = Selection { +// try $0.on( +// recommendError: .init { .error(errorMessage: try $0.errorCodes().first.toString()) }, +// recommendSuccess: .init { +// .saved(success: try $0.success()) +// } +// ) +// } +// +// let mutation = Selection.Mutation { +// try $0.recommend( +// input: .init(groupIds: groupIDs, note: OptionalArgument(note), pageId: pageID, recommendedWithHighlights: OptionalArgument(withHighlights)), +// selection: selection +// ) +// } +// +// let path = appEnvironment.graphqlPath +// let headers = networker.defaultHeaders +// +// return try await withCheckedThrowingContinuation { continuation in +// send(mutation, to: path, headers: headers) { queryResult in +// guard let payload = try? queryResult.get() else { +// continuation.resume(throwing: BasicError.message(messageText: "network error")) +// return +// } +// +// switch payload.data { +// case .saved: +// continuation.resume() +// case let .error(errorMessage: errorMessage): +// continuation.resume(throwing: BasicError.message(messageText: errorMessage)) +// } +// } +// } + throw BasicError.message(messageText: "Not Implemented") + } +}