diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift index 721680f70..70aa2f66e 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/ProfileView.swift @@ -78,6 +78,10 @@ struct ProfileView: View { NavigationLink(destination: NewsletterEmailsView()) { Text("Emails") } + + NavigationLink(destination: SubscriptionsView()) { + Text("Subscriptions") + } } Section { diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift new file mode 100644 index 000000000..675b91c7c --- /dev/null +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift @@ -0,0 +1,113 @@ +import Models +import Services +import SwiftUI +import Views + +@MainActor final class SubscriptionsViewModel: ObservableObject { + @Published var isLoading = false + @Published var emails = [NewsletterEmail]() + + func loadSubscriptions(dataService _: DataService) async { + isLoading = true + +// if let subscriptions = try? await dataService.subscriptions() { +// await dataService.viewContext.perform { [weak self] in +// self?.emails = objectIDs.compactMap { dataService.viewContext.object(with: $0) as? NewsletterEmail } +// } +// } + + isLoading = false + } + + func loadEmails(dataService: DataService) async { + isLoading = true + + if let objectIDs = try? await dataService.newsletterEmails() { + await dataService.viewContext.perform { [weak self] in + self?.emails = objectIDs.compactMap { dataService.viewContext.object(with: $0) as? NewsletterEmail } + } + } + + isLoading = false + } + + func createEmail(dataService: DataService) async { + isLoading = true + + if let objectID = try? await dataService.createNewsletter() { + await dataService.viewContext.perform { [weak self] in + if let item = dataService.viewContext.object(with: objectID) as? NewsletterEmail { + self?.emails.insert(item, at: 0) + } + } + } + + isLoading = false + } +} + +struct SubscriptionsView: View { + @EnvironmentObject var dataService: DataService + @StateObject var viewModel = SubscriptionsViewModel() + let footerText = "Add PDFs to your library, or subscribe to emails using an Omnivore email address." + + var body: some View { + Group { + #if os(iOS) + Form { + innerBody + } + #elseif os(macOS) + List { + innerBody + } + .listStyle(InsetListStyle()) + #endif + } + .task { await viewModel.loadEmails(dataService: dataService) } + } + + private var innerBody: some View { + Group { + Section(footer: Text(footerText)) { + Button( + action: { + Task { await viewModel.createEmail(dataService: dataService) } + }, + label: { + HStack { + Image(systemName: "plus.circle.fill").foregroundColor(.green) + Text("Create a new email address") + Spacer() + } + } + ) + .disabled(viewModel.isLoading) + } + + if !viewModel.emails.isEmpty { + Section(header: Text("Existing Emails (Tap to copy)")) { + ForEach(viewModel.emails) { newsletterEmail in + Button( + action: { + #if os(iOS) + UIPasteboard.general.string = newsletterEmail.email + #endif + + #if os(macOS) + let pasteBoard = NSPasteboard.general + pasteBoard.clearContents() + pasteBoard.writeObjects([newsletterEmail.unwrappedEmail as NSString]) + #endif + + Snackbar.show(message: "Email copied") + }, + label: { Text(newsletterEmail.unwrappedEmail) } + ) + } + } + } + } + .navigationTitle("Emails") + } +} diff --git a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift index 337fe8a6d..d2faed4b9 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift @@ -20,6 +20,136 @@ extension Objects.Subscription: GraphQLWebSocketOperation { // MARK: - Objects enum Objects {} +extension Objects { + struct AddPopularReadError { + let __typename: TypeName = .addPopularReadError + let errorCodes: [String: [Enums.AddPopularReadErrorCode]] + + enum TypeName: String, Codable { + case addPopularReadError = "AddPopularReadError" + } + } +} + +extension Objects.AddPopularReadError: 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.AddPopularReadErrorCode]?.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.AddPopularReadError { + func errorCodes() throws -> [Enums.AddPopularReadErrorCode] { + 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 AddPopularReadError = Selection +} + +extension Objects { + struct AddPopularReadSuccess { + let __typename: TypeName = .addPopularReadSuccess + let pageId: [String: String] + + enum TypeName: String, Codable { + case addPopularReadSuccess = "AddPopularReadSuccess" + } + } +} + +extension Objects.AddPopularReadSuccess: 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 "pageId": + 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)." + ) + ) + } + } + + pageId = map["pageId"] + } +} + +extension Fields where TypeLock == Objects.AddPopularReadSuccess { + func pageId() throws -> String { + let field = GraphQLField.leaf( + name: "pageId", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.pageId[field.alias!] { + return data + } + throw HttpError.badpayload + case .mocking: + return String.mockValue + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias AddPopularReadSuccess = Selection +} + extension Objects { struct ArchiveLinkError { let __typename: TypeName = .archiveLinkError @@ -6691,6 +6821,7 @@ extension Selection where TypeLock == Never, Type == Never { extension Objects { struct Mutation { let __typename: TypeName = .mutation + let addPopularRead: [String: Unions.AddPopularReadResult] let createArticle: [String: Unions.CreateArticleResult] let createArticleSavingRequest: [String: Unions.CreateArticleSavingRequestResult] let createHighlight: [String: Unions.CreateHighlightResult] @@ -6725,11 +6856,13 @@ extension Objects { let setShareHighlight: [String: Unions.SetShareHighlightResult] let setUserPersonalization: [String: Unions.SetUserPersonalizationResult] let signup: [String: Unions.SignupResult] + let subscribe: [String: Unions.SubscribeResult] let unsubscribe: [String: Unions.UnsubscribeResult] let updateHighlight: [String: Unions.UpdateHighlightResult] let updateHighlightReply: [String: Unions.UpdateHighlightReplyResult] let updateLabel: [String: Unions.UpdateLabelResult] let updateLinkShareInfo: [String: Unions.UpdateLinkShareInfoResult] + let updatePage: [String: Unions.UpdatePageResult] let updateReminder: [String: Unions.UpdateReminderResult] let updateSharedComment: [String: Unions.UpdateSharedCommentResult] let updateUser: [String: Unions.UpdateUserResult] @@ -6754,6 +6887,10 @@ extension Objects.Mutation: Decodable { let field = GraphQLField.getFieldNameFromAlias(alias) switch field { + case "addPopularRead": + if let value = try container.decode(Unions.AddPopularReadResult?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "createArticle": if let value = try container.decode(Unions.CreateArticleResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -6890,6 +7027,10 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.SignupResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "subscribe": + if let value = try container.decode(Unions.SubscribeResult?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "unsubscribe": if let value = try container.decode(Unions.UnsubscribeResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -6910,6 +7051,10 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.UpdateLinkShareInfoResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "updatePage": + if let value = try container.decode(Unions.UpdatePageResult?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "updateReminder": if let value = try container.decode(Unions.UpdateReminderResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -6940,6 +7085,7 @@ extension Objects.Mutation: Decodable { } } + addPopularRead = map["addPopularRead"] createArticle = map["createArticle"] createArticleSavingRequest = map["createArticleSavingRequest"] createHighlight = map["createHighlight"] @@ -6974,11 +7120,13 @@ extension Objects.Mutation: Decodable { setShareHighlight = map["setShareHighlight"] setUserPersonalization = map["setUserPersonalization"] signup = map["signup"] + subscribe = map["subscribe"] unsubscribe = map["unsubscribe"] updateHighlight = map["updateHighlight"] updateHighlightReply = map["updateHighlightReply"] updateLabel = map["updateLabel"] updateLinkShareInfo = map["updateLinkShareInfo"] + updatePage = map["updatePage"] updateReminder = map["updateReminder"] updateSharedComment = map["updateSharedComment"] updateUser = map["updateUser"] @@ -6988,6 +7136,25 @@ extension Objects.Mutation: Decodable { } extension Fields where TypeLock == Objects.Mutation { + func addPopularRead(name: String, selection: Selection) throws -> Type { + let field = GraphQLField.composite( + name: "addPopularRead", + arguments: [Argument(name: "name", type: "String!", value: name)], + selection: selection.selection + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.addPopularRead[field.alias!] { + return try selection.decode(data: data) + } + throw HttpError.badpayload + case .mocking: + return selection.mock() + } + } + func createArticle(input: InputObjects.CreateArticleInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "createArticle", @@ -7634,6 +7801,25 @@ extension Fields where TypeLock == Objects.Mutation { } } + func subscribe(name: String, selection: Selection) throws -> Type { + let field = GraphQLField.composite( + name: "subscribe", + arguments: [Argument(name: "name", type: "String!", value: name)], + selection: selection.selection + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.subscribe[field.alias!] { + return try selection.decode(data: data) + } + throw HttpError.badpayload + case .mocking: + return selection.mock() + } + } + func unsubscribe(name: String, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "unsubscribe", @@ -7729,6 +7915,25 @@ extension Fields where TypeLock == Objects.Mutation { } } + func updatePage(input: InputObjects.UpdatePageInput, selection: Selection) throws -> Type { + let field = GraphQLField.composite( + name: "updatePage", + arguments: [Argument(name: "input", type: "UpdatePageInput!", value: input)], + selection: selection.selection + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.updatePage[field.alias!] { + return try selection.decode(data: data) + } + throw HttpError.badpayload + case .mocking: + return selection.mock() + } + } + func updateReminder(input: InputObjects.UpdateReminderInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "updateReminder", @@ -10225,6 +10430,7 @@ extension Objects { let readingProgressAnchorIndex: [String: Int] let readingProgressPercent: [String: Double] let shortId: [String: String] + let siteName: [String: String] let slug: [String: String] let state: [String: Enums.ArticleSavingRequestStatus] let subscription: [String: String] @@ -10324,6 +10530,10 @@ extension Objects.SearchItem: Decodable { if let value = try container.decode(String?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "siteName": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "slug": if let value = try container.decode(String?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -10384,6 +10594,7 @@ extension Objects.SearchItem: Decodable { readingProgressAnchorIndex = map["readingProgressAnchorIndex"] readingProgressPercent = map["readingProgressPercent"] shortId = map["shortId"] + siteName = map["siteName"] slug = map["slug"] state = map["state"] subscription = map["subscription"] @@ -10682,6 +10893,21 @@ extension Fields where TypeLock == Objects.SearchItem { } } + func siteName() throws -> String? { + let field = GraphQLField.leaf( + name: "siteName", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.siteName[field.alias!] + case .mocking: + return nil + } + } + func slug() throws -> String { let field = GraphQLField.leaf( name: "slug", @@ -12332,6 +12558,137 @@ extension Selection where TypeLock == Never, Type == Never { typealias SignupSuccess = Selection } +extension Objects { + struct SubscribeError { + let __typename: TypeName = .subscribeError + let errorCodes: [String: [Enums.SubscribeErrorCode]] + + enum TypeName: String, Codable { + case subscribeError = "SubscribeError" + } + } +} + +extension Objects.SubscribeError: 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.SubscribeErrorCode]?.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.SubscribeError { + func errorCodes() throws -> [Enums.SubscribeErrorCode] { + 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 SubscribeError = Selection +} + +extension Objects { + struct SubscribeSuccess { + let __typename: TypeName = .subscribeSuccess + let subscriptions: [String: [Objects.Subscription]] + + enum TypeName: String, Codable { + case subscribeSuccess = "SubscribeSuccess" + } + } +} + +extension Objects.SubscribeSuccess: 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 "subscriptions": + if let value = try container.decode([Objects.Subscription]?.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)." + ) + ) + } + } + + subscriptions = map["subscriptions"] + } +} + +extension Fields where TypeLock == Objects.SubscribeSuccess { + func subscriptions(selection: Selection) throws -> Type { + let field = GraphQLField.composite( + name: "subscriptions", + arguments: [], + selection: selection.selection + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.subscriptions[field.alias!] { + return try selection.decode(data: data) + } + throw HttpError.badpayload + case .mocking: + return selection.mock() + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias SubscribeSuccess = Selection +} + extension Objects { struct Subscription { let __typename: TypeName = .subscription @@ -13386,6 +13743,137 @@ extension Selection where TypeLock == Never, Type == Never { typealias UpdateLinkShareInfoSuccess = Selection } +extension Objects { + struct UpdatePageError { + let __typename: TypeName = .updatePageError + let errorCodes: [String: [Enums.UpdatePageErrorCode]] + + enum TypeName: String, Codable { + case updatePageError = "UpdatePageError" + } + } +} + +extension Objects.UpdatePageError: 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.UpdatePageErrorCode]?.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.UpdatePageError { + func errorCodes() throws -> [Enums.UpdatePageErrorCode] { + 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 UpdatePageError = Selection +} + +extension Objects { + struct UpdatePageSuccess { + let __typename: TypeName = .updatePageSuccess + let updatedPage: [String: Objects.Page] + + enum TypeName: String, Codable { + case updatePageSuccess = "UpdatePageSuccess" + } + } +} + +extension Objects.UpdatePageSuccess: 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 "updatedPage": + if let value = try container.decode(Objects.Page?.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)." + ) + ) + } + } + + updatedPage = map["updatedPage"] + } +} + +extension Fields where TypeLock == Objects.UpdatePageSuccess { + func updatedPage(selection: Selection) throws -> Type { + let field = GraphQLField.composite( + name: "updatedPage", + arguments: [], + selection: selection.selection + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.updatedPage[field.alias!] { + return try selection.decode(data: data) + } + throw HttpError.badpayload + case .mocking: + return selection.mock() + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias UpdatePageSuccess = Selection +} + extension Objects { struct UpdateReminderError { let __typename: TypeName = .updateReminderError @@ -14891,6 +15379,80 @@ enum Interfaces {} // MARK: - Unions enum Unions {} +extension Unions { + struct AddPopularReadResult { + let __typename: TypeName + let errorCodes: [String: [Enums.AddPopularReadErrorCode]] + let pageId: [String: String] + + enum TypeName: String, Codable { + case addPopularReadError = "AddPopularReadError" + case addPopularReadSuccess = "AddPopularReadSuccess" + } + } +} + +extension Unions.AddPopularReadResult: 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.AddPopularReadErrorCode]?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "pageId": + 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"] + pageId = map["pageId"] + } +} + +extension Fields where TypeLock == Unions.AddPopularReadResult { + func on(addPopularReadError: Selection, addPopularReadSuccess: Selection) throws -> Type { + select([GraphQLField.fragment(type: "AddPopularReadError", selection: addPopularReadError.selection), GraphQLField.fragment(type: "AddPopularReadSuccess", selection: addPopularReadSuccess.selection)]) + + switch response { + case let .decoding(data): + switch data.__typename { + case .addPopularReadError: + let data = Objects.AddPopularReadError(errorCodes: data.errorCodes) + return try addPopularReadError.decode(data: data) + case .addPopularReadSuccess: + let data = Objects.AddPopularReadSuccess(pageId: data.pageId) + return try addPopularReadSuccess.decode(data: data) + } + case .mocking: + return addPopularReadError.mock() + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias AddPopularReadResult = Selection +} + extension Unions { struct ArchiveLinkResult { let __typename: TypeName @@ -18065,6 +18627,80 @@ extension Selection where TypeLock == Never, Type == Never { typealias SignupResult = Selection } +extension Unions { + struct SubscribeResult { + let __typename: TypeName + let errorCodes: [String: [Enums.SubscribeErrorCode]] + let subscriptions: [String: [Objects.Subscription]] + + enum TypeName: String, Codable { + case subscribeError = "SubscribeError" + case subscribeSuccess = "SubscribeSuccess" + } + } +} + +extension Unions.SubscribeResult: 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.SubscribeErrorCode]?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "subscriptions": + if let value = try container.decode([Objects.Subscription]?.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"] + subscriptions = map["subscriptions"] + } +} + +extension Fields where TypeLock == Unions.SubscribeResult { + func on(subscribeError: Selection, subscribeSuccess: Selection) throws -> Type { + select([GraphQLField.fragment(type: "SubscribeError", selection: subscribeError.selection), GraphQLField.fragment(type: "SubscribeSuccess", selection: subscribeSuccess.selection)]) + + switch response { + case let .decoding(data): + switch data.__typename { + case .subscribeError: + let data = Objects.SubscribeError(errorCodes: data.errorCodes) + return try subscribeError.decode(data: data) + case .subscribeSuccess: + let data = Objects.SubscribeSuccess(subscriptions: data.subscriptions) + return try subscribeSuccess.decode(data: data) + } + case .mocking: + return subscribeError.mock() + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias SubscribeResult = Selection +} + extension Unions { struct SubscriptionsResult { let __typename: TypeName @@ -18509,6 +19145,80 @@ extension Selection where TypeLock == Never, Type == Never { typealias UpdateLinkShareInfoResult = Selection } +extension Unions { + struct UpdatePageResult { + let __typename: TypeName + let errorCodes: [String: [Enums.UpdatePageErrorCode]] + let updatedPage: [String: Objects.Page] + + enum TypeName: String, Codable { + case updatePageError = "UpdatePageError" + case updatePageSuccess = "UpdatePageSuccess" + } + } +} + +extension Unions.UpdatePageResult: 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.UpdatePageErrorCode]?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "updatedPage": + if let value = try container.decode(Objects.Page?.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"] + updatedPage = map["updatedPage"] + } +} + +extension Fields where TypeLock == Unions.UpdatePageResult { + func on(updatePageError: Selection, updatePageSuccess: Selection) throws -> Type { + select([GraphQLField.fragment(type: "UpdatePageError", selection: updatePageError.selection), GraphQLField.fragment(type: "UpdatePageSuccess", selection: updatePageSuccess.selection)]) + + switch response { + case let .decoding(data): + switch data.__typename { + case .updatePageError: + let data = Objects.UpdatePageError(errorCodes: data.errorCodes) + return try updatePageError.decode(data: data) + case .updatePageSuccess: + let data = Objects.UpdatePageSuccess(updatedPage: data.updatedPage) + return try updatePageSuccess.decode(data: data) + } + case .mocking: + return updatePageError.mock() + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias UpdatePageResult = Selection +} + extension Unions { struct UpdateReminderResult { let __typename: TypeName @@ -19048,6 +19758,17 @@ extension Selection where TypeLock == Never, Type == Never { // MARK: - Enums enum Enums {} +extension Enums { + /// AddPopularReadErrorCode + enum AddPopularReadErrorCode: String, CaseIterable, Codable { + case badRequest = "BAD_REQUEST" + + case notFound = "NOT_FOUND" + + case unauthorized = "UNAUTHORIZED" + } +} + extension Enums { /// ArchiveLinkErrorCode enum ArchiveLinkErrorCode: String, CaseIterable, Codable { @@ -19551,6 +20272,8 @@ extension Enums { extension Enums { /// SortBy enum SortBy: String, CaseIterable, Codable { + case publishedAt = "PUBLISHED_AT" + case savedAt = "SAVED_AT" case score = "SCORE" @@ -19568,6 +20291,19 @@ extension Enums { } } +extension Enums { + /// SubscribeErrorCode + enum SubscribeErrorCode: String, CaseIterable, Codable { + case alreadySubscribed = "ALREADY_SUBSCRIBED" + + case badRequest = "BAD_REQUEST" + + case notFound = "NOT_FOUND" + + case unauthorized = "UNAUTHORIZED" + } +} + extension Enums { /// SubscriptionsErrorCode enum SubscriptionsErrorCode: String, CaseIterable, Codable { @@ -19649,6 +20385,21 @@ extension Enums { } } +extension Enums { + /// UpdatePageErrorCode + enum UpdatePageErrorCode: String, CaseIterable, Codable { + case badRequest = "BAD_REQUEST" + + case forbidden = "FORBIDDEN" + + case notFound = "NOT_FOUND" + + case unauthorized = "UNAUTHORIZED" + + case updateFailed = "UPDATE_FAILED" + } +} + extension Enums { /// UpdateReminderErrorCode enum UpdateReminderErrorCode: String, CaseIterable, Codable { @@ -20604,6 +21355,29 @@ extension InputObjects { } } +extension InputObjects { + struct UpdatePageInput: Encodable, Hashable { + var description: OptionalArgument = .absent() + + var pageId: String + + var title: OptionalArgument = .absent() + + 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(pageId, forKey: .pageId) + if title.hasValue { try container.encode(title, forKey: .title) } + } + + enum CodingKeys: String, CodingKey { + case description + case pageId + case title + } + } +} + extension InputObjects { struct UpdateReminderInput: Encodable, Hashable { var archiveUntil: Bool