diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift
index e73aa03f8..10ecb95af 100644
--- a/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift
+++ b/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift
@@ -107,6 +107,12 @@ struct ProfileView: View {
}
#endif
+ Section {
+ NavigationLink(destination: GroupsView()) {
+ Text("Recommendation Groups")
+ }
+ }
+
Section {
NavigationLink(
destination: BasicWebAppView.privacyPolicyWebView(baseURL: dataService.appEnvironment.webAppBaseURL)
diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupView.swift
new file mode 100644
index 000000000..e4bdcba4e
--- /dev/null
+++ b/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupView.swift
@@ -0,0 +1,74 @@
+import Models
+import Services
+import SwiftUI
+import Views
+
+@MainActor final class RecommendationsGroupViewModel: ObservableObject {
+ @Published var isLoading = false
+ @Published var networkError = true
+ @Published var recommendationGroup: InternalRecommendationGroup
+
+ init(recommendationGroup: InternalRecommendationGroup) {
+ self.recommendationGroup = recommendationGroup
+ }
+
+ func loadGroups(dataService _: DataService) async {
+ isLoading = true
+
+// do {
+// recommendationGroups = try await dataService.recommendationGroups()
+// } catch {
+// networkError = true
+// }
+
+ isLoading = false
+ }
+}
+
+struct RecommendationGroupView: View {
+ @EnvironmentObject var dataService: DataService
+ @StateObject var viewModel: RecommendationsGroupViewModel
+
+ var body: some View {
+ Group {
+ #if os(iOS)
+ Form {
+ innerBody
+ }
+ #elseif os(macOS)
+ List {
+ innerBody
+ }
+ .listStyle(InsetListStyle())
+ #endif
+ }
+ .task { await viewModel.loadGroups(dataService: dataService) }
+ }
+
+ private var innerBody: some View {
+ Group {
+ Section("Name") {
+ Text(viewModel.recommendationGroup.name)
+ }
+
+ Section("Invite Link") {
+ Button(action: {
+ #if os(iOS)
+ UIPasteboard.general.string = viewModel.recommendationGroup.inviteUrl
+ #endif
+
+ #if os(macOS)
+ let pasteBoard = NSPasteboard.general
+ pasteBoard.clearContents()
+ pasteBoard.writeObjects([viewModel.recommendationGroup.inviteUrl as NSString])
+ #endif
+
+ Snackbar.show(message: "Invite link copied")
+ }, label: {
+ Text("[\(viewModel.recommendationGroup.inviteUrl)](\(viewModel.recommendationGroup.inviteUrl))")
+ })
+ }
+ }
+ .navigationTitle(viewModel.recommendationGroup.name)
+ }
+}
diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupsView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupsView.swift
new file mode 100644
index 000000000..570072b41
--- /dev/null
+++ b/apple/OmnivoreKit/Sources/App/Views/Profile/RecommendationGroupsView.swift
@@ -0,0 +1,145 @@
+import Models
+import Services
+import SwiftUI
+import Views
+
+@MainActor final class RecommendationsGroupsViewModel: ObservableObject {
+ @Published var isLoading = false
+ @Published var isCreating = false
+ @Published var networkError = true
+ @Published var recommendationGroups = [InternalRecommendationGroup]()
+
+ @Published var showCreateSheet = false
+
+ @Published var showCreateError = false
+ @Published var createGroupError: String?
+
+ func loadGroups(dataService: DataService) async {
+ isLoading = true
+
+ do {
+ recommendationGroups = try await dataService.recommendationGroups()
+ } catch {
+ networkError = true
+ }
+
+ isLoading = false
+ }
+
+ func createGroup(dataService: DataService, name: String) async {
+ isCreating = true
+
+ if let group = try? await dataService.createRecommendationGroup(name: name) {
+ print("CREATED GROUP: ", group)
+ await loadGroups(dataService: dataService)
+ showCreateSheet = false
+ } else {
+ createGroupError = "Error creating group"
+ showCreateError = true
+ }
+
+ isCreating = false
+ }
+}
+
+struct CreateRecommendationGroupView: View {
+ @State var name = ""
+ @EnvironmentObject var dataService: DataService
+ @StateObject var viewModel = RecommendationsGroupsViewModel()
+
+ var nextButton: some View {
+ if viewModel.isCreating {
+ return AnyView(ProgressView())
+ } else {
+ return AnyView(Button(action: {
+ Task {
+ await viewModel.createGroup(dataService: dataService, name: self.name)
+ }
+ }, label: {
+ Text("Next")
+ })
+ .disabled(name.isEmpty)
+ )
+ }
+ }
+
+ var body: some View {
+ NavigationView {
+ Form {
+ TextField("Name", text: $name, prompt: Text("Group Name"))
+ }
+ .alert(isPresented: $viewModel.showCreateError) {
+ Alert(
+ title: Text(viewModel.createGroupError ?? "Error creating group"),
+ dismissButton: .cancel(Text("Ok")) {
+ viewModel.createGroupError = nil
+ viewModel.showCreateError = false
+ }
+ )
+ }
+ }
+ .navigationViewStyle(.stack)
+ .navigationTitle("Create Group")
+ .navigationBarTitleDisplayMode(.inline)
+ .navigationBarItems(leading:
+ Button(action: {
+ viewModel.showCreateSheet = false
+ }, label: { Text("Cancel") }),
+ trailing: nextButton)
+ }
+}
+
+struct GroupsView: View {
+ @EnvironmentObject var dataService: DataService
+ @StateObject var viewModel = RecommendationsGroupsViewModel()
+
+ var body: some View {
+ Group {
+ #if os(iOS)
+ Form {
+ innerBody
+ }
+ #elseif os(macOS)
+ List {
+ innerBody
+ }
+ .listStyle(InsetListStyle())
+ #endif
+ }
+ .sheet(isPresented: $viewModel.showCreateSheet) {
+ NavigationView {
+ CreateRecommendationGroupView(viewModel: self.viewModel)
+ }
+ }
+ .task { await viewModel.loadGroups(dataService: dataService) }
+ }
+
+ private var innerBody: some View {
+ Group {
+ Section {
+ Button(
+ action: { viewModel.showCreateSheet = true },
+ label: {
+ HStack {
+ Image(systemName: "plus.circle.fill").foregroundColor(.green)
+ Text("Create a new group")
+ Spacer()
+ }
+ }
+ )
+ .disabled(viewModel.isLoading)
+ }
+
+ Section(header: Text("Your recommendation groups")) {
+ ForEach(viewModel.recommendationGroups) { recommendationGroup in
+ NavigationLink(
+ destination: RecommendationGroupView(viewModel: RecommendationsGroupViewModel(recommendationGroup: recommendationGroup))
+ ) {
+ Text(recommendationGroup.name)
+ }
+ }
+ }
+ }
+ .navigationTitle("Recommendation Groups")
+ }
+}
diff --git a/apple/OmnivoreKit/Sources/Models/CoreData/CoreDataModel.xcdatamodeld/CoreDataModel.xcdatamodel/contents b/apple/OmnivoreKit/Sources/Models/CoreData/CoreDataModel.xcdatamodeld/CoreDataModel.xcdatamodel/contents
index ace07414f..4b026f83e 100644
--- a/apple/OmnivoreKit/Sources/Models/CoreData/CoreDataModel.xcdatamodeld/CoreDataModel.xcdatamodel/contents
+++ b/apple/OmnivoreKit/Sources/Models/CoreData/CoreDataModel.xcdatamodeld/CoreDataModel.xcdatamodel/contents
@@ -91,6 +91,13 @@
+
+
+
+
+
+
+
diff --git a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift
index 2b4d961e2..c5554e066 100644
--- a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift
+++ b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift
@@ -2596,6 +2596,137 @@ extension Selection where TypeLock == Never, Type == Never {
typealias CreateArticleSuccess = Selection
}
+extension Objects {
+ struct CreateGroupError {
+ let __typename: TypeName = .createGroupError
+ let errorCodes: [String: [Enums.CreateGroupErrorCode]]
+
+ enum TypeName: String, Codable {
+ case createGroupError = "CreateGroupError"
+ }
+ }
+}
+
+extension Objects.CreateGroupError: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.CreateGroupErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ errorCodes = map["errorCodes"]
+ }
+}
+
+extension Fields where TypeLock == Objects.CreateGroupError {
+ func errorCodes() throws -> [Enums.CreateGroupErrorCode] {
+ let field = GraphQLField.leaf(
+ name: "errorCodes",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.errorCodes[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return []
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias CreateGroupError = Selection
+}
+
+extension Objects {
+ struct CreateGroupSuccess {
+ let __typename: TypeName = .createGroupSuccess
+ let group: [String: Objects.RecommendationGroup]
+
+ enum TypeName: String, Codable {
+ case createGroupSuccess = "CreateGroupSuccess"
+ }
+ }
+}
+
+extension Objects.CreateGroupSuccess: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "group":
+ if let value = try container.decode(Objects.RecommendationGroup?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ group = map["group"]
+ }
+}
+
+extension Fields where TypeLock == Objects.CreateGroupSuccess {
+ func group(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "group",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.group[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias CreateGroupSuccess = Selection
+}
+
extension Objects {
struct CreateHighlightError {
let __typename: TypeName = .createHighlightError
@@ -3512,6 +3643,137 @@ extension Selection where TypeLock == Never, Type == Never {
typealias DeleteAccountSuccess = Selection
}
+extension Objects {
+ struct DeleteFilterError {
+ let __typename: TypeName = .deleteFilterError
+ let errorCodes: [String: [Enums.DeleteFilterErrorCode]]
+
+ enum TypeName: String, Codable {
+ case deleteFilterError = "DeleteFilterError"
+ }
+ }
+}
+
+extension Objects.DeleteFilterError: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.DeleteFilterErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ errorCodes = map["errorCodes"]
+ }
+}
+
+extension Fields where TypeLock == Objects.DeleteFilterError {
+ func errorCodes() throws -> [Enums.DeleteFilterErrorCode] {
+ let field = GraphQLField.leaf(
+ name: "errorCodes",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.errorCodes[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return []
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias DeleteFilterError = Selection
+}
+
+extension Objects {
+ struct DeleteFilterSuccess {
+ let __typename: TypeName = .deleteFilterSuccess
+ let filter: [String: Objects.Filter]
+
+ enum TypeName: String, Codable {
+ case deleteFilterSuccess = "DeleteFilterSuccess"
+ }
+ }
+}
+
+extension Objects.DeleteFilterSuccess: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "filter":
+ if let value = try container.decode(Objects.Filter?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ filter = map["filter"]
+ }
+}
+
+extension Fields where TypeLock == Objects.DeleteFilterSuccess {
+ func filter(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "filter",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.filter[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias DeleteFilterSuccess = Selection
+}
+
extension Objects {
struct DeleteHighlightError {
let __typename: TypeName = .deleteHighlightError
@@ -5654,6 +5916,343 @@ extension Selection where TypeLock == Never, Type == Never {
typealias FeedArticlesSuccess = Selection
}
+extension Objects {
+ struct Filter {
+ let __typename: TypeName = .filter
+ let createdAt: [String: DateTime]
+ let description: [String: String]
+ let filter: [String: String]
+ let id: [String: String]
+ let name: [String: String]
+ let position: [String: Int]
+ let updatedAt: [String: DateTime]
+
+ enum TypeName: String, Codable {
+ case filter = "Filter"
+ }
+ }
+}
+
+extension Objects.Filter: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "createdAt":
+ if let value = try container.decode(DateTime?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "description":
+ if let value = try container.decode(String?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "filter":
+ if let value = try container.decode(String?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "id":
+ if let value = try container.decode(String?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "name":
+ if let value = try container.decode(String?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "position":
+ if let value = try container.decode(Int?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "updatedAt":
+ if let value = try container.decode(DateTime?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ createdAt = map["createdAt"]
+ description = map["description"]
+ filter = map["filter"]
+ id = map["id"]
+ name = map["name"]
+ position = map["position"]
+ updatedAt = map["updatedAt"]
+ }
+}
+
+extension Fields where TypeLock == Objects.Filter {
+ func createdAt() throws -> DateTime {
+ let field = GraphQLField.leaf(
+ name: "createdAt",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.createdAt[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return DateTime.mockValue
+ }
+ }
+
+ func description() throws -> String? {
+ let field = GraphQLField.leaf(
+ name: "description",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ return data.description[field.alias!]
+ case .mocking:
+ return nil
+ }
+ }
+
+ func filter() throws -> String {
+ let field = GraphQLField.leaf(
+ name: "filter",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.filter[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return String.mockValue
+ }
+ }
+
+ func id() throws -> String {
+ let field = GraphQLField.leaf(
+ name: "id",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.id[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return String.mockValue
+ }
+ }
+
+ func name() throws -> String {
+ let field = GraphQLField.leaf(
+ name: "name",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.name[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return String.mockValue
+ }
+ }
+
+ func position() throws -> Int {
+ let field = GraphQLField.leaf(
+ name: "position",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.position[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return Int.mockValue
+ }
+ }
+
+ func updatedAt() throws -> DateTime {
+ let field = GraphQLField.leaf(
+ name: "updatedAt",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.updatedAt[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return DateTime.mockValue
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias Filter = Selection
+}
+
+extension Objects {
+ struct FiltersError {
+ let __typename: TypeName = .filtersError
+ let errorCodes: [String: [Enums.FiltersErrorCode]]
+
+ enum TypeName: String, Codable {
+ case filtersError = "FiltersError"
+ }
+ }
+}
+
+extension Objects.FiltersError: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.FiltersErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ errorCodes = map["errorCodes"]
+ }
+}
+
+extension Fields where TypeLock == Objects.FiltersError {
+ func errorCodes() throws -> [Enums.FiltersErrorCode] {
+ let field = GraphQLField.leaf(
+ name: "errorCodes",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.errorCodes[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return []
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias FiltersError = Selection
+}
+
+extension Objects {
+ struct FiltersSuccess {
+ let __typename: TypeName = .filtersSuccess
+ let filters: [String: [Objects.Filter]]
+
+ enum TypeName: String, Codable {
+ case filtersSuccess = "FiltersSuccess"
+ }
+ }
+}
+
+extension Objects.FiltersSuccess: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "filters":
+ if let value = try container.decode([Objects.Filter]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ filters = map["filters"]
+ }
+}
+
+extension Fields where TypeLock == Objects.FiltersSuccess {
+ func filters(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "filters",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.filters[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias FiltersSuccess = Selection
+}
+
extension Objects {
struct GenerateApiKeyError {
let __typename: TypeName = .generateApiKeyError
@@ -6306,6 +6905,137 @@ extension Selection where TypeLock == Never, Type == Never {
typealias GoogleSignupSuccess = Selection
}
+extension Objects {
+ struct GroupsError {
+ let __typename: TypeName = .groupsError
+ let errorCodes: [String: [Enums.GroupsErrorCode]]
+
+ enum TypeName: String, Codable {
+ case groupsError = "GroupsError"
+ }
+ }
+}
+
+extension Objects.GroupsError: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.GroupsErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ errorCodes = map["errorCodes"]
+ }
+}
+
+extension Fields where TypeLock == Objects.GroupsError {
+ func errorCodes() throws -> [Enums.GroupsErrorCode] {
+ let field = GraphQLField.leaf(
+ name: "errorCodes",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.errorCodes[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return []
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias GroupsError = Selection
+}
+
+extension Objects {
+ struct GroupsSuccess {
+ let __typename: TypeName = .groupsSuccess
+ let groups: [String: [Objects.RecommendationGroup]]
+
+ enum TypeName: String, Codable {
+ case groupsSuccess = "GroupsSuccess"
+ }
+ }
+}
+
+extension Objects.GroupsSuccess: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "groups":
+ if let value = try container.decode([Objects.RecommendationGroup]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ groups = map["groups"]
+ }
+}
+
+extension Fields where TypeLock == Objects.GroupsSuccess {
+ func groups(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "groups",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.groups[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias GroupsSuccess = Selection
+}
+
extension Objects {
struct Highlight {
let __typename: TypeName = .highlight
@@ -8498,6 +9228,137 @@ extension Selection where TypeLock == Never, Type == Never {
typealias MergeHighlightSuccess = Selection
}
+extension Objects {
+ struct MoveFilterError {
+ let __typename: TypeName = .moveFilterError
+ let errorCodes: [String: [Enums.MoveFilterErrorCode]]
+
+ enum TypeName: String, Codable {
+ case moveFilterError = "MoveFilterError"
+ }
+ }
+}
+
+extension Objects.MoveFilterError: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.MoveFilterErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ errorCodes = map["errorCodes"]
+ }
+}
+
+extension Fields where TypeLock == Objects.MoveFilterError {
+ func errorCodes() throws -> [Enums.MoveFilterErrorCode] {
+ let field = GraphQLField.leaf(
+ name: "errorCodes",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.errorCodes[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return []
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias MoveFilterError = Selection
+}
+
+extension Objects {
+ struct MoveFilterSuccess {
+ let __typename: TypeName = .moveFilterSuccess
+ let filter: [String: Objects.Filter]
+
+ enum TypeName: String, Codable {
+ case moveFilterSuccess = "MoveFilterSuccess"
+ }
+ }
+}
+
+extension Objects.MoveFilterSuccess: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "filter":
+ if let value = try container.decode(Objects.Filter?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ filter = map["filter"]
+ }
+}
+
+extension Fields where TypeLock == Objects.MoveFilterSuccess {
+ func filter(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "filter",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.filter[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias MoveFilterSuccess = Selection
+}
+
extension Objects {
struct MoveLabelError {
let __typename: TypeName = .moveLabelError
@@ -8635,6 +9496,7 @@ extension Objects {
let addPopularRead: [String: Unions.AddPopularReadResult]
let createArticle: [String: Unions.CreateArticleResult]
let createArticleSavingRequest: [String: Unions.CreateArticleSavingRequestResult]
+ let createGroup: [String: Unions.CreateGroupResult]
let createHighlight: [String: Unions.CreateHighlightResult]
let createHighlightReply: [String: Unions.CreateHighlightReplyResult]
let createLabel: [String: Unions.CreateLabelResult]
@@ -8642,6 +9504,7 @@ extension Objects {
let createReaction: [String: Unions.CreateReactionResult]
let createReminder: [String: Unions.CreateReminderResult]
let deleteAccount: [String: Unions.DeleteAccountResult]
+ let deleteFilter: [String: Unions.DeleteFilterResult]
let deleteHighlight: [String: Unions.DeleteHighlightResult]
let deleteHighlightReply: [String: Unions.DeleteHighlightReplyResult]
let deleteIntegration: [String: Unions.DeleteIntegrationResult]
@@ -8656,12 +9519,15 @@ extension Objects {
let googleSignup: [String: Unions.GoogleSignupResult]
let logOut: [String: Unions.LogOutResult]
let mergeHighlight: [String: Unions.MergeHighlightResult]
+ let moveFilter: [String: Unions.MoveFilterResult]
let moveLabel: [String: Unions.MoveLabelResult]
let optInFeature: [String: Unions.OptInFeatureResult]
+ let recommend: [String: Unions.RecommendResult]
let reportItem: [String: Objects.ReportItemResult]
let revokeApiKey: [String: Unions.RevokeApiKeyResult]
let saveArticleReadingProgress: [String: Unions.SaveArticleReadingProgressResult]
let saveFile: [String: Unions.SaveResult]
+ let saveFilter: [String: Unions.SaveFilterResult]
let savePage: [String: Unions.SaveResult]
let saveUrl: [String: Unions.SaveResult]
let setBookmarkArticle: [String: Unions.SetBookmarkArticleResult]
@@ -8719,6 +9585,10 @@ extension Objects.Mutation: Decodable {
if let value = try container.decode(Unions.CreateArticleSavingRequestResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
+ case "createGroup":
+ if let value = try container.decode(Unions.CreateGroupResult?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
case "createHighlight":
if let value = try container.decode(Unions.CreateHighlightResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@@ -8747,6 +9617,10 @@ extension Objects.Mutation: Decodable {
if let value = try container.decode(Unions.DeleteAccountResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
+ case "deleteFilter":
+ if let value = try container.decode(Unions.DeleteFilterResult?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
case "deleteHighlight":
if let value = try container.decode(Unions.DeleteHighlightResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@@ -8803,6 +9677,10 @@ extension Objects.Mutation: Decodable {
if let value = try container.decode(Unions.MergeHighlightResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
+ case "moveFilter":
+ if let value = try container.decode(Unions.MoveFilterResult?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
case "moveLabel":
if let value = try container.decode(Unions.MoveLabelResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@@ -8811,6 +9689,10 @@ extension Objects.Mutation: Decodable {
if let value = try container.decode(Unions.OptInFeatureResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
+ case "recommend":
+ if let value = try container.decode(Unions.RecommendResult?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
case "reportItem":
if let value = try container.decode(Objects.ReportItemResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@@ -8827,6 +9709,10 @@ extension Objects.Mutation: Decodable {
if let value = try container.decode(Unions.SaveResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
+ case "saveFilter":
+ if let value = try container.decode(Unions.SaveFilterResult?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
case "savePage":
if let value = try container.decode(Unions.SaveResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@@ -8944,6 +9830,7 @@ extension Objects.Mutation: Decodable {
addPopularRead = map["addPopularRead"]
createArticle = map["createArticle"]
createArticleSavingRequest = map["createArticleSavingRequest"]
+ createGroup = map["createGroup"]
createHighlight = map["createHighlight"]
createHighlightReply = map["createHighlightReply"]
createLabel = map["createLabel"]
@@ -8951,6 +9838,7 @@ extension Objects.Mutation: Decodable {
createReaction = map["createReaction"]
createReminder = map["createReminder"]
deleteAccount = map["deleteAccount"]
+ deleteFilter = map["deleteFilter"]
deleteHighlight = map["deleteHighlight"]
deleteHighlightReply = map["deleteHighlightReply"]
deleteIntegration = map["deleteIntegration"]
@@ -8965,12 +9853,15 @@ extension Objects.Mutation: Decodable {
googleSignup = map["googleSignup"]
logOut = map["logOut"]
mergeHighlight = map["mergeHighlight"]
+ moveFilter = map["moveFilter"]
moveLabel = map["moveLabel"]
optInFeature = map["optInFeature"]
+ recommend = map["recommend"]
reportItem = map["reportItem"]
revokeApiKey = map["revokeApiKey"]
saveArticleReadingProgress = map["saveArticleReadingProgress"]
saveFile = map["saveFile"]
+ saveFilter = map["saveFilter"]
savePage = map["savePage"]
saveUrl = map["saveUrl"]
setBookmarkArticle = map["setBookmarkArticle"]
@@ -9058,6 +9949,25 @@ extension Fields where TypeLock == Objects.Mutation {
}
}
+ func createGroup(input: InputObjects.CreateGroupInput, selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "createGroup",
+ arguments: [Argument(name: "input", type: "CreateGroupInput!", value: input)],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.createGroup[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+
func createHighlight(input: InputObjects.CreateHighlightInput, selection: Selection) throws -> Type {
let field = GraphQLField.composite(
name: "createHighlight",
@@ -9191,6 +10101,25 @@ extension Fields where TypeLock == Objects.Mutation {
}
}
+ func deleteFilter(id: String, selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "deleteFilter",
+ arguments: [Argument(name: "id", type: "ID!", value: id)],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.deleteFilter[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+
func deleteHighlight(highlightId: String, selection: Selection) throws -> Type {
let field = GraphQLField.composite(
name: "deleteHighlight",
@@ -9457,6 +10386,25 @@ extension Fields where TypeLock == Objects.Mutation {
}
}
+ func moveFilter(input: InputObjects.MoveFilterInput, selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "moveFilter",
+ arguments: [Argument(name: "input", type: "MoveFilterInput!", value: input)],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.moveFilter[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+
func moveLabel(input: InputObjects.MoveLabelInput, selection: Selection) throws -> Type {
let field = GraphQLField.composite(
name: "moveLabel",
@@ -9495,6 +10443,25 @@ extension Fields where TypeLock == Objects.Mutation {
}
}
+ func recommend(input: InputObjects.RecommendInput, selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "recommend",
+ arguments: [Argument(name: "input", type: "RecommendInput!", value: input)],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.recommend[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+
func reportItem(input: InputObjects.ReportItemInput, selection: Selection) throws -> Type {
let field = GraphQLField.composite(
name: "reportItem",
@@ -9571,6 +10538,25 @@ extension Fields where TypeLock == Objects.Mutation {
}
}
+ func saveFilter(input: InputObjects.SaveFilterInput, selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "saveFilter",
+ arguments: [Argument(name: "input", type: "SaveFilterInput!", value: input)],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.saveFilter[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+
func savePage(input: InputObjects.SavePageInput, selection: Selection) throws -> Type {
let field = GraphQLField.composite(
name: "savePage",
@@ -11126,9 +12112,11 @@ extension Objects {
let articles: [String: Unions.ArticlesResult]
let deviceTokens: [String: Unions.DeviceTokensResult]
let feedArticles: [String: Unions.FeedArticlesResult]
+ let filters: [String: Unions.FiltersResult]
let getFollowers: [String: Unions.GetFollowersResult]
let getFollowing: [String: Unions.GetFollowingResult]
let getUserPersonalization: [String: Unions.GetUserPersonalizationResult]
+ let groups: [String: Unions.GroupsResult]
let hello: [String: String]
let integrations: [String: Unions.IntegrationsResult]
let labels: [String: Unions.LabelsResult]
@@ -11191,6 +12179,10 @@ extension Objects.Query: Decodable {
if let value = try container.decode(Unions.FeedArticlesResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
+ case "filters":
+ if let value = try container.decode(Unions.FiltersResult?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
case "getFollowers":
if let value = try container.decode(Unions.GetFollowersResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@@ -11203,6 +12195,10 @@ extension Objects.Query: Decodable {
if let value = try container.decode(Unions.GetUserPersonalizationResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
+ case "groups":
+ if let value = try container.decode(Unions.GroupsResult?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
case "hello":
if let value = try container.decode(String?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@@ -11295,9 +12291,11 @@ extension Objects.Query: Decodable {
articles = map["articles"]
deviceTokens = map["deviceTokens"]
feedArticles = map["feedArticles"]
+ filters = map["filters"]
getFollowers = map["getFollowers"]
getFollowing = map["getFollowing"]
getUserPersonalization = map["getUserPersonalization"]
+ groups = map["groups"]
hello = map["hello"]
integrations = map["integrations"]
labels = map["labels"]
@@ -11435,6 +12433,25 @@ extension Fields where TypeLock == Objects.Query {
}
}
+ func filters(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "filters",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.filters[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+
func getFollowers(userId: OptionalArgument = .absent(), selection: Selection) throws -> Type {
let field = GraphQLField.composite(
name: "getFollowers",
@@ -11492,6 +12509,25 @@ extension Fields where TypeLock == Objects.Query {
}
}
+ func groups(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "groups",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.groups[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+
func hello() throws -> String? {
let field = GraphQLField.leaf(
name: "hello",
@@ -12384,6 +13420,347 @@ extension Selection where TypeLock == Never, Type == Never {
typealias RecentSearchesSuccess = Selection
}
+extension Objects {
+ struct RecommendError {
+ let __typename: TypeName = .recommendError
+ let errorCodes: [String: [Enums.RecommendErrorCode]]
+
+ enum TypeName: String, Codable {
+ case recommendError = "RecommendError"
+ }
+ }
+}
+
+extension Objects.RecommendError: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.RecommendErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ errorCodes = map["errorCodes"]
+ }
+}
+
+extension Fields where TypeLock == Objects.RecommendError {
+ func errorCodes() throws -> [Enums.RecommendErrorCode] {
+ let field = GraphQLField.leaf(
+ name: "errorCodes",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.errorCodes[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return []
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias RecommendError = Selection
+}
+
+extension Objects {
+ struct RecommendSuccess {
+ let __typename: TypeName = .recommendSuccess
+ let taskNames: [String: [String]]
+
+ enum TypeName: String, Codable {
+ case recommendSuccess = "RecommendSuccess"
+ }
+ }
+}
+
+extension Objects.RecommendSuccess: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "taskNames":
+ if let value = try container.decode([String]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ taskNames = map["taskNames"]
+ }
+}
+
+extension Fields where TypeLock == Objects.RecommendSuccess {
+ func taskNames() throws -> [String] {
+ let field = GraphQLField.leaf(
+ name: "taskNames",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.taskNames[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return []
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias RecommendSuccess = Selection
+}
+
+extension Objects {
+ struct RecommendationGroup {
+ let __typename: TypeName = .recommendationGroup
+ let admins: [String: [Objects.User]]
+ let createdAt: [String: DateTime]
+ let id: [String: String]
+ let inviteUrl: [String: String]
+ let members: [String: [Objects.User]]
+ let name: [String: String]
+ let updatedAt: [String: DateTime]
+
+ enum TypeName: String, Codable {
+ case recommendationGroup = "RecommendationGroup"
+ }
+ }
+}
+
+extension Objects.RecommendationGroup: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "admins":
+ if let value = try container.decode([Objects.User]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "createdAt":
+ if let value = try container.decode(DateTime?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "id":
+ if let value = try container.decode(String?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "inviteUrl":
+ if let value = try container.decode(String?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "members":
+ if let value = try container.decode([Objects.User]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "name":
+ if let value = try container.decode(String?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "updatedAt":
+ if let value = try container.decode(DateTime?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ admins = map["admins"]
+ createdAt = map["createdAt"]
+ id = map["id"]
+ inviteUrl = map["inviteUrl"]
+ members = map["members"]
+ name = map["name"]
+ updatedAt = map["updatedAt"]
+ }
+}
+
+extension Fields where TypeLock == Objects.RecommendationGroup {
+ func admins(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "admins",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.admins[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+
+ func createdAt() throws -> DateTime {
+ let field = GraphQLField.leaf(
+ name: "createdAt",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.createdAt[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return DateTime.mockValue
+ }
+ }
+
+ func id() throws -> String {
+ let field = GraphQLField.leaf(
+ name: "id",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.id[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return String.mockValue
+ }
+ }
+
+ func inviteUrl() throws -> String {
+ let field = GraphQLField.leaf(
+ name: "inviteUrl",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.inviteUrl[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return String.mockValue
+ }
+ }
+
+ func members(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "members",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.members[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+
+ func name() throws -> String {
+ let field = GraphQLField.leaf(
+ name: "name",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.name[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return String.mockValue
+ }
+ }
+
+ func updatedAt() throws -> DateTime {
+ let field = GraphQLField.leaf(
+ name: "updatedAt",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.updatedAt[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return DateTime.mockValue
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias RecommendationGroup = Selection
+}
+
extension Objects {
struct Reminder {
let __typename: TypeName = .reminder
@@ -13495,6 +14872,137 @@ extension Selection where TypeLock == Never, Type == Never {
typealias SaveError = Selection
}
+extension Objects {
+ struct SaveFilterError {
+ let __typename: TypeName = .saveFilterError
+ let errorCodes: [String: [Enums.SaveFilterErrorCode]]
+
+ enum TypeName: String, Codable {
+ case saveFilterError = "SaveFilterError"
+ }
+ }
+}
+
+extension Objects.SaveFilterError: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.SaveFilterErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ errorCodes = map["errorCodes"]
+ }
+}
+
+extension Fields where TypeLock == Objects.SaveFilterError {
+ func errorCodes() throws -> [Enums.SaveFilterErrorCode] {
+ let field = GraphQLField.leaf(
+ name: "errorCodes",
+ arguments: []
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.errorCodes[field.alias!] {
+ return data
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return []
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias SaveFilterError = Selection
+}
+
+extension Objects {
+ struct SaveFilterSuccess {
+ let __typename: TypeName = .saveFilterSuccess
+ let filter: [String: Objects.Filter]
+
+ enum TypeName: String, Codable {
+ case saveFilterSuccess = "SaveFilterSuccess"
+ }
+ }
+}
+
+extension Objects.SaveFilterSuccess: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "filter":
+ if let value = try container.decode(Objects.Filter?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ filter = map["filter"]
+ }
+}
+
+extension Fields where TypeLock == Objects.SaveFilterSuccess {
+ func filter(selection: Selection) throws -> Type {
+ let field = GraphQLField.composite(
+ name: "filter",
+ arguments: [],
+ selection: selection.selection
+ )
+ select(field)
+
+ switch response {
+ case let .decoding(data):
+ if let data = data.filter[field.alias!] {
+ return try selection.decode(data: data)
+ }
+ throw HttpError.badpayload
+ case .mocking:
+ return selection.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias SaveFilterSuccess = Selection
+}
+
extension Objects {
struct SaveSuccess {
let __typename: TypeName = .saveSuccess
@@ -20940,6 +22448,80 @@ extension Selection where TypeLock == Never, Type == Never {
typealias CreateArticleSavingRequestResult = Selection
}
+extension Unions {
+ struct CreateGroupResult {
+ let __typename: TypeName
+ let errorCodes: [String: [Enums.CreateGroupErrorCode]]
+ let group: [String: Objects.RecommendationGroup]
+
+ enum TypeName: String, Codable {
+ case createGroupError = "CreateGroupError"
+ case createGroupSuccess = "CreateGroupSuccess"
+ }
+ }
+}
+
+extension Unions.CreateGroupResult: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.CreateGroupErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "group":
+ if let value = try container.decode(Objects.RecommendationGroup?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ __typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!)
+
+ errorCodes = map["errorCodes"]
+ group = map["group"]
+ }
+}
+
+extension Fields where TypeLock == Unions.CreateGroupResult {
+ func on(createGroupError: Selection, createGroupSuccess: Selection) throws -> Type {
+ select([GraphQLField.fragment(type: "CreateGroupError", selection: createGroupError.selection), GraphQLField.fragment(type: "CreateGroupSuccess", selection: createGroupSuccess.selection)])
+
+ switch response {
+ case let .decoding(data):
+ switch data.__typename {
+ case .createGroupError:
+ let data = Objects.CreateGroupError(errorCodes: data.errorCodes)
+ return try createGroupError.decode(data: data)
+ case .createGroupSuccess:
+ let data = Objects.CreateGroupSuccess(group: data.group)
+ return try createGroupSuccess.decode(data: data)
+ }
+ case .mocking:
+ return createGroupError.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias CreateGroupResult = Selection
+}
+
extension Unions {
struct CreateHighlightReplyResult {
let __typename: TypeName
@@ -21458,6 +23040,80 @@ extension Selection where TypeLock == Never, Type == Never {
typealias DeleteAccountResult = Selection
}
+extension Unions {
+ struct DeleteFilterResult {
+ let __typename: TypeName
+ let errorCodes: [String: [Enums.DeleteFilterErrorCode]]
+ let filter: [String: Objects.Filter]
+
+ enum TypeName: String, Codable {
+ case deleteFilterError = "DeleteFilterError"
+ case deleteFilterSuccess = "DeleteFilterSuccess"
+ }
+ }
+}
+
+extension Unions.DeleteFilterResult: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.DeleteFilterErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "filter":
+ if let value = try container.decode(Objects.Filter?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ __typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!)
+
+ errorCodes = map["errorCodes"]
+ filter = map["filter"]
+ }
+}
+
+extension Fields where TypeLock == Unions.DeleteFilterResult {
+ func on(deleteFilterError: Selection, deleteFilterSuccess: Selection) throws -> Type {
+ select([GraphQLField.fragment(type: "DeleteFilterError", selection: deleteFilterError.selection), GraphQLField.fragment(type: "DeleteFilterSuccess", selection: deleteFilterSuccess.selection)])
+
+ switch response {
+ case let .decoding(data):
+ switch data.__typename {
+ case .deleteFilterError:
+ let data = Objects.DeleteFilterError(errorCodes: data.errorCodes)
+ return try deleteFilterError.decode(data: data)
+ case .deleteFilterSuccess:
+ let data = Objects.DeleteFilterSuccess(filter: data.filter)
+ return try deleteFilterSuccess.decode(data: data)
+ }
+ case .mocking:
+ return deleteFilterError.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias DeleteFilterResult = Selection
+}
+
extension Unions {
struct DeleteHighlightReplyResult {
let __typename: TypeName
@@ -22278,6 +23934,80 @@ extension Selection where TypeLock == Never, Type == Never {
typealias FeedArticlesResult = Selection
}
+extension Unions {
+ struct FiltersResult {
+ let __typename: TypeName
+ let errorCodes: [String: [Enums.FiltersErrorCode]]
+ let filters: [String: [Objects.Filter]]
+
+ enum TypeName: String, Codable {
+ case filtersError = "FiltersError"
+ case filtersSuccess = "FiltersSuccess"
+ }
+ }
+}
+
+extension Unions.FiltersResult: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.FiltersErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "filters":
+ if let value = try container.decode([Objects.Filter]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ __typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!)
+
+ errorCodes = map["errorCodes"]
+ filters = map["filters"]
+ }
+}
+
+extension Fields where TypeLock == Unions.FiltersResult {
+ func on(filtersError: Selection, filtersSuccess: Selection) throws -> Type {
+ select([GraphQLField.fragment(type: "FiltersError", selection: filtersError.selection), GraphQLField.fragment(type: "FiltersSuccess", selection: filtersSuccess.selection)])
+
+ switch response {
+ case let .decoding(data):
+ switch data.__typename {
+ case .filtersError:
+ let data = Objects.FiltersError(errorCodes: data.errorCodes)
+ return try filtersError.decode(data: data)
+ case .filtersSuccess:
+ let data = Objects.FiltersSuccess(filters: data.filters)
+ return try filtersSuccess.decode(data: data)
+ }
+ case .mocking:
+ return filtersError.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias FiltersResult = Selection
+}
+
extension Unions {
struct GenerateApiKeyResult {
let __typename: TypeName
@@ -22648,6 +24378,80 @@ extension Selection where TypeLock == Never, Type == Never {
typealias GoogleSignupResult = Selection
}
+extension Unions {
+ struct GroupsResult {
+ let __typename: TypeName
+ let errorCodes: [String: [Enums.GroupsErrorCode]]
+ let groups: [String: [Objects.RecommendationGroup]]
+
+ enum TypeName: String, Codable {
+ case groupsError = "GroupsError"
+ case groupsSuccess = "GroupsSuccess"
+ }
+ }
+}
+
+extension Unions.GroupsResult: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.GroupsErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "groups":
+ if let value = try container.decode([Objects.RecommendationGroup]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ __typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!)
+
+ errorCodes = map["errorCodes"]
+ groups = map["groups"]
+ }
+}
+
+extension Fields where TypeLock == Unions.GroupsResult {
+ func on(groupsError: Selection, groupsSuccess: Selection) throws -> Type {
+ select([GraphQLField.fragment(type: "GroupsError", selection: groupsError.selection), GraphQLField.fragment(type: "GroupsSuccess", selection: groupsSuccess.selection)])
+
+ switch response {
+ case let .decoding(data):
+ switch data.__typename {
+ case .groupsError:
+ let data = Objects.GroupsError(errorCodes: data.errorCodes)
+ return try groupsError.decode(data: data)
+ case .groupsSuccess:
+ let data = Objects.GroupsSuccess(groups: data.groups)
+ return try groupsSuccess.decode(data: data)
+ }
+ case .mocking:
+ return groupsError.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias GroupsResult = Selection
+}
+
extension Unions {
struct IntegrationsResult {
let __typename: TypeName
@@ -23024,6 +24828,80 @@ extension Selection where TypeLock == Never, Type == Never {
typealias MergeHighlightResult = Selection
}
+extension Unions {
+ struct MoveFilterResult {
+ let __typename: TypeName
+ let errorCodes: [String: [Enums.MoveFilterErrorCode]]
+ let filter: [String: Objects.Filter]
+
+ enum TypeName: String, Codable {
+ case moveFilterError = "MoveFilterError"
+ case moveFilterSuccess = "MoveFilterSuccess"
+ }
+ }
+}
+
+extension Unions.MoveFilterResult: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.MoveFilterErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "filter":
+ if let value = try container.decode(Objects.Filter?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ __typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!)
+
+ errorCodes = map["errorCodes"]
+ filter = map["filter"]
+ }
+}
+
+extension Fields where TypeLock == Unions.MoveFilterResult {
+ func on(moveFilterError: Selection, moveFilterSuccess: Selection) throws -> Type {
+ select([GraphQLField.fragment(type: "MoveFilterError", selection: moveFilterError.selection), GraphQLField.fragment(type: "MoveFilterSuccess", selection: moveFilterSuccess.selection)])
+
+ switch response {
+ case let .decoding(data):
+ switch data.__typename {
+ case .moveFilterError:
+ let data = Objects.MoveFilterError(errorCodes: data.errorCodes)
+ return try moveFilterError.decode(data: data)
+ case .moveFilterSuccess:
+ let data = Objects.MoveFilterSuccess(filter: data.filter)
+ return try moveFilterSuccess.decode(data: data)
+ }
+ case .mocking:
+ return moveFilterError.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias MoveFilterResult = Selection
+}
+
extension Unions {
struct MoveLabelResult {
let __typename: TypeName
@@ -23320,6 +25198,80 @@ extension Selection where TypeLock == Never, Type == Never {
typealias RecentSearchesResult = Selection
}
+extension Unions {
+ struct RecommendResult {
+ let __typename: TypeName
+ let errorCodes: [String: [Enums.RecommendErrorCode]]
+ let taskNames: [String: [String]]
+
+ enum TypeName: String, Codable {
+ case recommendError = "RecommendError"
+ case recommendSuccess = "RecommendSuccess"
+ }
+ }
+}
+
+extension Unions.RecommendResult: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.RecommendErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "taskNames":
+ if let value = try container.decode([String]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ __typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!)
+
+ errorCodes = map["errorCodes"]
+ taskNames = map["taskNames"]
+ }
+}
+
+extension Fields where TypeLock == Unions.RecommendResult {
+ func on(recommendError: Selection, recommendSuccess: Selection) throws -> Type {
+ select([GraphQLField.fragment(type: "RecommendError", selection: recommendError.selection), GraphQLField.fragment(type: "RecommendSuccess", selection: recommendSuccess.selection)])
+
+ switch response {
+ case let .decoding(data):
+ switch data.__typename {
+ case .recommendError:
+ let data = Objects.RecommendError(errorCodes: data.errorCodes)
+ return try recommendError.decode(data: data)
+ case .recommendSuccess:
+ let data = Objects.RecommendSuccess(taskNames: data.taskNames)
+ return try recommendSuccess.decode(data: data)
+ }
+ case .mocking:
+ return recommendError.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias RecommendResult = Selection
+}
+
extension Unions {
struct ReminderResult {
let __typename: TypeName
@@ -23616,6 +25568,80 @@ extension Selection where TypeLock == Never, Type == Never {
typealias SaveArticleReadingProgressResult = Selection
}
+extension Unions {
+ struct SaveFilterResult {
+ let __typename: TypeName
+ let errorCodes: [String: [Enums.SaveFilterErrorCode]]
+ let filter: [String: Objects.Filter]
+
+ enum TypeName: String, Codable {
+ case saveFilterError = "SaveFilterError"
+ case saveFilterSuccess = "SaveFilterSuccess"
+ }
+ }
+}
+
+extension Unions.SaveFilterResult: Decodable {
+ init(from decoder: Decoder) throws {
+ let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
+
+ var map = HashMap()
+ for codingKey in container.allKeys {
+ if codingKey.isTypenameKey { continue }
+
+ let alias = codingKey.stringValue
+ let field = GraphQLField.getFieldNameFromAlias(alias)
+
+ switch field {
+ case "errorCodes":
+ if let value = try container.decode([Enums.SaveFilterErrorCode]?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ case "filter":
+ if let value = try container.decode(Objects.Filter?.self, forKey: codingKey) {
+ map.set(key: field, hash: alias, value: value as Any)
+ }
+ default:
+ throw DecodingError.dataCorrupted(
+ DecodingError.Context(
+ codingPath: decoder.codingPath,
+ debugDescription: "Unknown key \(field)."
+ )
+ )
+ }
+ }
+
+ __typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!)
+
+ errorCodes = map["errorCodes"]
+ filter = map["filter"]
+ }
+}
+
+extension Fields where TypeLock == Unions.SaveFilterResult {
+ func on(saveFilterError: Selection, saveFilterSuccess: Selection) throws -> Type {
+ select([GraphQLField.fragment(type: "SaveFilterError", selection: saveFilterError.selection), GraphQLField.fragment(type: "SaveFilterSuccess", selection: saveFilterSuccess.selection)])
+
+ switch response {
+ case let .decoding(data):
+ switch data.__typename {
+ case .saveFilterError:
+ let data = Objects.SaveFilterError(errorCodes: data.errorCodes)
+ return try saveFilterError.decode(data: data)
+ case .saveFilterSuccess:
+ let data = Objects.SaveFilterSuccess(filter: data.filter)
+ return try saveFilterSuccess.decode(data: data)
+ }
+ case .mocking:
+ return saveFilterError.mock()
+ }
+ }
+}
+
+extension Selection where TypeLock == Never, Type == Never {
+ typealias SaveFilterResult = Selection
+}
+
extension Unions {
struct SaveResult {
let __typename: TypeName
@@ -26227,6 +28253,15 @@ extension Enums {
}
}
+extension Enums {
+ /// CreateGroupErrorCode
+ enum CreateGroupErrorCode: String, CaseIterable, Codable {
+ case badRequest = "BAD_REQUEST"
+
+ case unauthorized = "UNAUTHORIZED"
+ }
+}
+
extension Enums {
/// CreateHighlightErrorCode
enum CreateHighlightErrorCode: String, CaseIterable, Codable {
@@ -26314,6 +28349,17 @@ extension Enums {
}
}
+extension Enums {
+ /// DeleteFilterErrorCode
+ enum DeleteFilterErrorCode: String, CaseIterable, Codable {
+ case badRequest = "BAD_REQUEST"
+
+ case notFound = "NOT_FOUND"
+
+ case unauthorized = "UNAUTHORIZED"
+ }
+}
+
extension Enums {
/// DeleteHighlightErrorCode
enum DeleteHighlightErrorCode: String, CaseIterable, Codable {
@@ -26429,6 +28475,15 @@ extension Enums {
}
}
+extension Enums {
+ /// FiltersErrorCode
+ enum FiltersErrorCode: String, CaseIterable, Codable {
+ case badRequest = "BAD_REQUEST"
+
+ case unauthorized = "UNAUTHORIZED"
+ }
+}
+
extension Enums {
/// GenerateApiKeyErrorCode
enum GenerateApiKeyErrorCode: String, CaseIterable, Codable {
@@ -26461,6 +28516,15 @@ extension Enums {
}
}
+extension Enums {
+ /// GroupsErrorCode
+ enum GroupsErrorCode: String, CaseIterable, Codable {
+ case badRequest = "BAD_REQUEST"
+
+ case unauthorized = "UNAUTHORIZED"
+ }
+}
+
extension Enums {
/// IntegrationType
enum IntegrationType: String, CaseIterable, Codable {
@@ -26527,6 +28591,17 @@ extension Enums {
}
}
+extension Enums {
+ /// MoveFilterErrorCode
+ enum MoveFilterErrorCode: String, CaseIterable, Codable {
+ case badRequest = "BAD_REQUEST"
+
+ case notFound = "NOT_FOUND"
+
+ case unauthorized = "UNAUTHORIZED"
+ }
+}
+
extension Enums {
/// MoveLabelErrorCode
enum MoveLabelErrorCode: String, CaseIterable, Codable {
@@ -26601,6 +28676,17 @@ extension Enums {
}
}
+extension Enums {
+ /// RecommendErrorCode
+ enum RecommendErrorCode: String, CaseIterable, Codable {
+ case badRequest = "BAD_REQUEST"
+
+ case notFound = "NOT_FOUND"
+
+ case unauthorized = "UNAUTHORIZED"
+ }
+}
+
extension Enums {
/// ReminderErrorCode
enum ReminderErrorCode: String, CaseIterable, Codable {
@@ -26680,6 +28766,17 @@ extension Enums {
}
}
+extension Enums {
+ /// SaveFilterErrorCode
+ enum SaveFilterErrorCode: String, CaseIterable, Codable {
+ case badRequest = "BAD_REQUEST"
+
+ case notFound = "NOT_FOUND"
+
+ case unauthorized = "UNAUTHORIZED"
+ }
+}
+
extension Enums {
/// SearchErrorCode
enum SearchErrorCode: String, CaseIterable, Codable {
@@ -27208,6 +29305,29 @@ extension InputObjects {
}
}
+extension InputObjects {
+ struct CreateGroupInput: Encodable, Hashable {
+ var expiresInDays: OptionalArgument = .absent()
+
+ var maxMembers: OptionalArgument = .absent()
+
+ var name: String
+
+ func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ if expiresInDays.hasValue { try container.encode(expiresInDays, forKey: .expiresInDays) }
+ if maxMembers.hasValue { try container.encode(maxMembers, forKey: .maxMembers) }
+ try container.encode(name, forKey: .name)
+ }
+
+ enum CodingKeys: String, CodingKey {
+ case expiresInDays
+ case maxMembers
+ case name
+ }
+ }
+}
+
extension InputObjects {
struct CreateHighlightInput: Encodable, Hashable {
var annotation: OptionalArgument = .absent()
@@ -27495,6 +29615,25 @@ extension InputObjects {
}
}
+extension InputObjects {
+ struct MoveFilterInput: Encodable, Hashable {
+ var afterFilterId: OptionalArgument = .absent()
+
+ var filterId: String
+
+ func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ if afterFilterId.hasValue { try container.encode(afterFilterId, forKey: .afterFilterId) }
+ try container.encode(filterId, forKey: .filterId)
+ }
+
+ enum CodingKeys: String, CodingKey {
+ case afterFilterId
+ case filterId
+ }
+ }
+}
+
extension InputObjects {
struct MoveLabelInput: Encodable, Hashable {
var afterLabelId: OptionalArgument = .absent()
@@ -27587,6 +29726,25 @@ extension InputObjects {
}
}
+extension InputObjects {
+ struct RecommendInput: Encodable, Hashable {
+ var groupIds: [String]
+
+ var pageId: String
+
+ func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ try container.encode(groupIds, forKey: .groupIds)
+ try container.encode(pageId, forKey: .pageId)
+ }
+
+ enum CodingKeys: String, CodingKey {
+ case groupIds
+ case pageId
+ }
+ }
+}
+
extension InputObjects {
struct ReportItemInput: Encodable, Hashable {
var itemUrl: String
@@ -27687,6 +29845,33 @@ extension InputObjects {
}
}
+extension InputObjects {
+ struct SaveFilterInput: Encodable, Hashable {
+ var description: OptionalArgument = .absent()
+
+ var filter: String
+
+ var id: OptionalArgument = .absent()
+
+ var name: String
+
+ func encode(to encoder: Encoder) throws {
+ var container = encoder.container(keyedBy: CodingKeys.self)
+ if description.hasValue { try container.encode(description, forKey: .description) }
+ try container.encode(filter, forKey: .filter)
+ if id.hasValue { try container.encode(id, forKey: .id) }
+ try container.encode(name, forKey: .name)
+ }
+
+ enum CodingKeys: String, CodingKey {
+ case description
+ case filter
+ case id
+ case name
+ }
+ }
+}
+
extension InputObjects {
struct SavePageInput: Encodable, Hashable {
var clientRequestId: String
@@ -28149,6 +30334,8 @@ extension InputObjects {
var pageId: String
+ var savedAt: OptionalArgument = .absent()
+
var title: OptionalArgument = .absent()
func encode(to encoder: Encoder) throws {
@@ -28156,6 +30343,7 @@ extension InputObjects {
if byline.hasValue { try container.encode(byline, forKey: .byline) }
if description.hasValue { try container.encode(description, forKey: .description) }
try container.encode(pageId, forKey: .pageId)
+ if savedAt.hasValue { try container.encode(savedAt, forKey: .savedAt) }
if title.hasValue { try container.encode(title, forKey: .title) }
}
@@ -28163,6 +30351,7 @@ extension InputObjects {
case byline
case description
case pageId
+ case savedAt
case title
}
}
diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/CreateRecommendationGroup.swift b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/CreateRecommendationGroup.swift
new file mode 100644
index 000000000..646cf45dc
--- /dev/null
+++ b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/CreateRecommendationGroup.swift
@@ -0,0 +1,53 @@
+import CoreData
+import Foundation
+import Models
+import SwiftGraphQL
+
+public extension DataService {
+ func createRecommendationGroup(name: String) async throws -> InternalRecommendationGroup {
+ enum MutationResult {
+ case saved(recommendationGroup: InternalRecommendationGroup)
+ case error(errorCode: Enums.CreateGroupErrorCode)
+ }
+
+ let selection = Selection {
+ try $0.on(
+ createGroupError: .init {
+ .error(errorCode: try $0.errorCodes().first ?? .badRequest)
+ },
+ createGroupSuccess: .init {
+ .saved(recommendationGroup: try $0.group(selection: recommendationGroupSelection))
+ }
+ )
+ }
+
+ let input = InputObjects.CreateGroupInput(name: name)
+
+ let mutation = Selection.Mutation {
+ try $0.createGroup(input: input, selection: selection)
+ }
+
+ let path = appEnvironment.graphqlPath
+ let headers = networker.defaultHeaders
+
+ return try await withCheckedThrowingContinuation { continuation in
+ send(mutation, to: path, headers: headers) { [weak self] queryResult in
+ guard let payload = try? queryResult.get(), let self = self else {
+ continuation.resume(throwing: BasicError.message(messageText: "network error"))
+ return
+ }
+
+ switch payload.data {
+ case let .saved(recommendationGroup: recommendationGroup):
+ if [recommendationGroup].persist(context: self.backgroundContext) != nil {
+ continuation.resume(returning: recommendationGroup)
+ } else {
+ continuation.resume(throwing: BasicError.message(messageText: "CoreData error"))
+ }
+ case let .error(errorCode: errorCode):
+ continuation.resume(throwing: BasicError.message(messageText: errorCode.rawValue))
+ }
+ }
+ }
+ }
+}
diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Queries/RecommendationGroupsQuery.swift b/apple/OmnivoreKit/Sources/Services/DataService/Queries/RecommendationGroupsQuery.swift
new file mode 100644
index 000000000..a17a5c52c
--- /dev/null
+++ b/apple/OmnivoreKit/Sources/Services/DataService/Queries/RecommendationGroupsQuery.swift
@@ -0,0 +1,52 @@
+import CoreData
+import Foundation
+import Models
+import SwiftGraphQL
+
+public extension DataService {
+ func recommendationGroups() async throws -> [InternalRecommendationGroup] {
+ enum QueryResult {
+ case success(result: [InternalRecommendationGroup])
+ case error(error: String)
+ }
+
+ let selection = Selection {
+ try $0.on(
+ groupsError: .init {
+ QueryResult.error(error: try $0.errorCodes().description)
+ },
+ groupsSuccess: .init {
+ QueryResult.success(result: try $0.groups(selection: recommendationGroupSelection.list))
+ }
+ )
+ }
+
+ let query = Selection.Query {
+ try $0.groups(selection: selection)
+ }
+
+ let path = appEnvironment.graphqlPath
+ let headers = networker.defaultHeaders
+ let context = backgroundContext
+
+ return try await withCheckedThrowingContinuation { continuation in
+ send(query, to: path, headers: headers) { queryResult in
+ guard let payload = try? queryResult.get() else {
+ continuation.resume(throwing: BasicError.message(messageText: "network request failed"))
+ return
+ }
+
+ switch payload.data {
+ case let .success(result: result):
+ if result.persist(context: context) != nil {
+ continuation.resume(returning: result)
+ } else {
+ continuation.resume(throwing: BasicError.message(messageText: "CoreData error"))
+ }
+ case .error:
+ continuation.resume(throwing: BasicError.message(messageText: "Recommendation Groups fetch error"))
+ }
+ }
+ }
+ }
+}
diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Selections/RecommendationGroupSelection.swift b/apple/OmnivoreKit/Sources/Services/DataService/Selections/RecommendationGroupSelection.swift
new file mode 100644
index 000000000..4064c1bf9
--- /dev/null
+++ b/apple/OmnivoreKit/Sources/Services/DataService/Selections/RecommendationGroupSelection.swift
@@ -0,0 +1,10 @@
+import Models
+import SwiftGraphQL
+
+let recommendationGroupSelection = Selection.RecommendationGroup {
+ InternalRecommendationGroup(
+ id: try $0.id(),
+ name: try $0.name(),
+ inviteUrl: try $0.inviteUrl()
+ )
+}
diff --git a/apple/OmnivoreKit/Sources/Services/InternalModels/InternalRecommendationGroup.swift b/apple/OmnivoreKit/Sources/Services/InternalModels/InternalRecommendationGroup.swift
new file mode 100644
index 000000000..c787cc1f8
--- /dev/null
+++ b/apple/OmnivoreKit/Sources/Services/InternalModels/InternalRecommendationGroup.swift
@@ -0,0 +1,65 @@
+//
+// InternalRecommendationGroup.swift
+//
+//
+// Created by Jackson Harper on 12/5/22.
+//
+
+import CoreData
+import Foundation
+import Models
+
+public struct InternalRecommendationGroup: Encodable, Identifiable {
+ public let id: String
+ public let name: String
+ public let inviteUrl: String
+
+ func asManagedObject(inContext context: NSManagedObjectContext) -> RecommendationGroup {
+ let fetchRequest: NSFetchRequest = RecommendationGroup.fetchRequest()
+ fetchRequest.predicate = NSPredicate(
+ format: "id == %@", id
+ )
+ let existing = (try? context.fetch(fetchRequest))?.first
+ let recommendationGroup = existing ?? RecommendationGroup(entity: RecommendationGroup.entity(), insertInto: context)
+
+ recommendationGroup.id = id
+ recommendationGroup.name = name
+ recommendationGroup.inviteUrl = inviteUrl
+
+ return recommendationGroup
+ }
+
+ static func make(from recommendationGroup: RecommendationGroup) -> InternalRecommendationGroup? {
+ if let id = recommendationGroup.id,
+ let name = recommendationGroup.name,
+ let inviteUrl = recommendationGroup.inviteUrl
+ {
+ return InternalRecommendationGroup(
+ id: id,
+ name: name,
+ inviteUrl: inviteUrl
+ )
+ }
+ return nil
+ }
+}
+
+extension Sequence where Element == InternalRecommendationGroup {
+ func persist(context: NSManagedObjectContext) -> [NSManagedObjectID]? {
+ var result: [NSManagedObjectID]?
+
+ context.performAndWait {
+ let recommendationGroups = map { $0.asManagedObject(inContext: context) }
+ do {
+ try context.save()
+ logger.debug("InternalRecommendationGroup saved succesfully")
+ result = recommendationGroups.map(\.objectID)
+ } catch {
+ context.rollback()
+ logger.debug("Failed to save InternalRecommendationGroups: \(error.localizedDescription)")
+ }
+ }
+
+ return result
+ }
+}