From 76c094b1ba4a15471bf192ec1383c9f0a5d3ef72 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 24 Oct 2023 19:27:09 +0800 Subject: [PATCH] Force reading position to update on iOS in PDFs --- .../Sources/App/PDFSupport/PDFViewer.swift | 13 +- .../App/PDFSupport/PDFViewerViewModel.swift | 5 +- .../App/Views/Home/HomeFeedViewModel.swift | 27 +- .../App/Views/LinkItemDetailView.swift | 3 +- .../Views/WebReader/WebReaderContainer.swift | 4 +- .../Views/WebReader/WebReaderViewModel.swift | 2 +- .../AudioSession/AudioController.swift | 2 +- .../Services/DataService/GQLSchema.swift | 1307 +++++++++-------- .../Mutations/CreateReminder.swift | 78 - .../UpdateArticleReadingProgress.swift | 16 +- .../Services/DataService/OfflineSync.swift | 3 +- .../Queries/ArticleContentQuery.swift | 2 +- .../Queries/LinkedItemNetworkQuery.swift | 2 +- .../Queries/SubscriptionsQuery.swift | 2 +- .../Selections/HighlightSelection.swift | 3 +- 15 files changed, 757 insertions(+), 712 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewer.swift b/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewer.swift index de8542a87..e525f5f66 100644 --- a/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewer.swift +++ b/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewer.swift @@ -237,13 +237,12 @@ import Utils let pageIndex = Int(event.pageIndex) if let totalPageCount = controller.document?.pageCount { let percent = min(100, max(0, ((Double(pageIndex) + 1.0) / Double(totalPageCount)) * 100.0)) - if percent > self.viewModel.pdfItem.readingProgress { - self.viewModel.updateItemReadProgress( - dataService: dataService, - percent: percent, - anchorIndex: pageIndex - ) - } + self.viewModel.updateItemReadProgress( + dataService: dataService, + percent: percent, + anchorIndex: pageIndex, + force: true + ) } } }.store(in: &subscriptions) diff --git a/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewerViewModel.swift b/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewerViewModel.swift index af5f05915..96f88a654 100644 --- a/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewerViewModel.swift +++ b/apple/OmnivoreKit/Sources/App/PDFSupport/PDFViewerViewModel.swift @@ -76,11 +76,12 @@ final class PDFViewerViewModel: ObservableObject { } } - func updateItemReadProgress(dataService: DataService, percent: Double, anchorIndex: Int) { + func updateItemReadProgress(dataService: DataService, percent: Double, anchorIndex: Int, force: Bool = false) { dataService.updateLinkReadingProgress( itemID: pdfItem.itemID, readingProgress: percent, - anchorIndex: anchorIndex + anchorIndex: anchorIndex, + force: force ) } diff --git a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift index 498ee5907..18b93c16b 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Home/HomeFeedViewModel.swift @@ -356,34 +356,11 @@ import Views } func markRead(dataService: DataService, item: LinkedItem) { - dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 100, anchorIndex: 0) + dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 100, anchorIndex: 0, force: true) } func markUnread(dataService: DataService, item: LinkedItem) { - dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0, anchorIndex: 0) - } - - func snoozeUntil(dataService: DataService, linkId: String, until: Date, successMessage: String?) async { - isLoading = true - - if let itemIndex = items.firstIndex(where: { $0.id == linkId }) { - items.remove(at: itemIndex) - } - - do { - try await dataService.createReminder( - reminderItemId: .link(id: linkId), - remindAt: until - ) - - if let message = successMessage { - snackbar(message) - } - } catch { - NSNotification.operationFailed(message: "Failed to snooze") - } - - isLoading = false + dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0, anchorIndex: 0, force: true) } private var queryContainsFilter: Bool { diff --git a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift index 1b7e4aa4a..c6149fce0 100644 --- a/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift +++ b/apple/OmnivoreKit/Sources/App/Views/LinkItemDetailView.swift @@ -39,7 +39,8 @@ import Views dataService.updateLinkReadingProgress( itemID: itemID, readingProgress: isItemRead ? 0 : 100, - anchorIndex: 0 + anchorIndex: 0, + force: false ) } diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift index f8a5ed8a2..040cc4f7c 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderContainer.swift @@ -233,7 +233,7 @@ struct WebReaderContainerView: View { ) Button( action: { - dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0, anchorIndex: 0) + dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0, anchorIndex: 0, force: true) }, label: { Label("Reset Read Location", systemImage: "arrow.counterclockwise.circle") } ) @@ -432,7 +432,7 @@ struct WebReaderContainerView: View { #endif .onAppear { if item.isUnread { - dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0.1, anchorIndex: 0) + dataService.updateLinkReadingProgress(itemID: item.unwrappedID, readingProgress: 0.1, anchorIndex: 0, force: false) } Task { await audioController.preload(itemIDs: [item.unwrappedID]) diff --git a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderViewModel.swift b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderViewModel.swift index 259f10079..2f29e5bc7 100644 --- a/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderViewModel.swift +++ b/apple/OmnivoreKit/Sources/App/Views/WebReader/WebReaderViewModel.swift @@ -171,7 +171,7 @@ struct SafariWebLink: Identifiable { return } - dataService.updateLinkReadingProgress(itemID: itemID, readingProgress: readingProgress, anchorIndex: anchorIndex) + dataService.updateLinkReadingProgress(itemID: itemID, readingProgress: readingProgress, anchorIndex: anchorIndex, force: false) replyHandler(["result": true], nil) } diff --git a/apple/OmnivoreKit/Sources/Services/AudioSession/AudioController.swift b/apple/OmnivoreKit/Sources/Services/AudioSession/AudioController.swift index a0e57e7a7..5fff16478 100644 --- a/apple/OmnivoreKit/Sources/Services/AudioSession/AudioController.swift +++ b/apple/OmnivoreKit/Sources/Services/AudioSession/AudioController.swift @@ -740,7 +740,7 @@ let anchorIndex = Int((player?.currentItem as? SpeechPlayerItem)?.speechItem.htmlIdx ?? "") ?? 0 if let itemID = itemAudioProperties?.itemID { - dataService.updateLinkReadingProgress(itemID: itemID, readingProgress: percentProgress, anchorIndex: anchorIndex) + dataService.updateLinkReadingProgress(itemID: itemID, readingProgress: percentProgress, anchorIndex: anchorIndex, force: true) } if let itemID = itemAudioProperties?.itemID, let player = player, let currentItem = player.currentItem { diff --git a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift index fb6283215..32e46f8f0 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift @@ -1515,7 +1515,7 @@ extension Fields where TypeLock == Objects.Article { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -1524,12 +1524,9 @@ extension Fields where TypeLock == Objects.Article { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } @@ -1941,7 +1938,7 @@ extension Fields where TypeLock == Objects.ArticleSavingRequest { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -1950,12 +1947,9 @@ extension Fields where TypeLock == Objects.ArticleSavingRequest { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } @@ -5595,7 +5589,7 @@ extension Fields where TypeLock == Objects.Feature { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -5604,12 +5598,9 @@ extension Fields where TypeLock == Objects.Feature { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } } @@ -6139,12 +6130,14 @@ extension Objects { let __typename: TypeName = .filter let category: [String: String] let createdAt: [String: DateTime] + let defaultFilter: [String: Bool] let description: [String: String] let filter: [String: String] let id: [String: String] let name: [String: String] let position: [String: Int] let updatedAt: [String: DateTime] + let visible: [String: Bool] enum TypeName: String, Codable { case filter = "Filter" @@ -6172,6 +6165,10 @@ extension Objects.Filter: Decodable { if let value = try container.decode(DateTime?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "defaultFilter": + if let value = try container.decode(Bool?.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) @@ -6196,6 +6193,10 @@ extension Objects.Filter: Decodable { if let value = try container.decode(DateTime?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "visible": + if let value = try container.decode(Bool?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } default: throw DecodingError.dataCorrupted( DecodingError.Context( @@ -6208,12 +6209,14 @@ extension Objects.Filter: Decodable { category = map["category"] createdAt = map["createdAt"] + defaultFilter = map["defaultFilter"] description = map["description"] filter = map["filter"] id = map["id"] name = map["name"] position = map["position"] updatedAt = map["updatedAt"] + visible = map["visible"] } } @@ -6254,6 +6257,21 @@ extension Fields where TypeLock == Objects.Filter { } } + func defaultFilter() throws -> Bool? { + let field = GraphQLField.leaf( + name: "defaultFilter", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.defaultFilter[field.alias!] + case .mocking: + return nil + } + } + func description() throws -> String? { let field = GraphQLField.leaf( name: "description", @@ -6341,7 +6359,7 @@ extension Fields where TypeLock == Objects.Filter { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -6350,12 +6368,24 @@ extension Fields where TypeLock == Objects.Filter { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil + } + } + + func visible() throws -> Bool? { + let field = GraphQLField.leaf( + name: "visible", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.visible[field.alias!] + case .mocking: + return nil } } } @@ -7728,7 +7758,7 @@ extension Fields where TypeLock == Objects.Highlight { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -7737,12 +7767,9 @@ extension Fields where TypeLock == Objects.Highlight { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } @@ -7915,7 +7942,7 @@ extension Fields where TypeLock == Objects.HighlightReply { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -7924,12 +7951,9 @@ extension Fields where TypeLock == Objects.HighlightReply { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } @@ -8359,7 +8383,7 @@ extension Fields where TypeLock == Objects.Integration { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -8368,12 +8392,9 @@ extension Fields where TypeLock == Objects.Integration { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } } @@ -9420,7 +9441,7 @@ extension Fields where TypeLock == Objects.Link { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -9429,12 +9450,9 @@ extension Fields where TypeLock == Objects.Link { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } @@ -10388,20 +10406,14 @@ extension Objects { 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] let createNewsletterEmail: [String: Unions.CreateNewsletterEmailResult] - 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] let deleteLabel: [String: Unions.DeleteLabelResult] let deleteNewsletterEmail: [String: Unions.DeleteNewsletterEmailResult] - let deleteReaction: [String: Unions.DeleteReactionResult] - let deleteReminder: [String: Unions.DeleteReminderResult] let deleteRule: [String: Unions.DeleteRuleResult] let deleteWebhook: [String: Unions.DeleteWebhookResult] let generateApiKey: [String: Unions.GenerateApiKeyResult] @@ -10428,25 +10440,20 @@ extension Objects { let setBookmarkArticle: [String: Unions.SetBookmarkArticleResult] let setDeviceToken: [String: Unions.SetDeviceTokenResult] let setFavoriteArticle: [String: Unions.SetFavoriteArticleResult] - let setFollow: [String: Unions.SetFollowResult] let setIntegration: [String: Unions.SetIntegrationResult] let setLabels: [String: Unions.SetLabelsResult] let setLabelsForHighlight: [String: Unions.SetLabelsResult] let setLinkArchived: [String: Unions.ArchiveLinkResult] let setRule: [String: Unions.SetRuleResult] - let setShareArticle: [String: Unions.SetShareArticleResult] - let setShareHighlight: [String: Unions.SetShareHighlightResult] let setUserPersonalization: [String: Unions.SetUserPersonalizationResult] let setWebhook: [String: Unions.SetWebhookResult] let subscribe: [String: Unions.SubscribeResult] let unsubscribe: [String: Unions.UnsubscribeResult] + let updateEmail: [String: Unions.UpdateEmailResult] + let updateFilter: [String: Unions.UpdateFilterResult] 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 updateSubscription: [String: Unions.UpdateSubscriptionResult] let updateUser: [String: Unions.UpdateUserResult] let updateUserProfile: [String: Unions.UpdateUserProfileResult] @@ -10495,10 +10502,6 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.CreateHighlightResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "createHighlightReply": - if let value = try container.decode(Unions.CreateHighlightReplyResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "createLabel": if let value = try container.decode(Unions.CreateLabelResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -10507,14 +10510,6 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.CreateNewsletterEmailResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "createReaction": - if let value = try container.decode(Unions.CreateReactionResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } - case "createReminder": - if let value = try container.decode(Unions.CreateReminderResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "deleteAccount": if let value = try container.decode(Unions.DeleteAccountResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -10527,10 +10522,6 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.DeleteHighlightResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "deleteHighlightReply": - if let value = try container.decode(Unions.DeleteHighlightReplyResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "deleteIntegration": if let value = try container.decode(Unions.DeleteIntegrationResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -10543,14 +10534,6 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.DeleteNewsletterEmailResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "deleteReaction": - if let value = try container.decode(Unions.DeleteReactionResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } - case "deleteReminder": - if let value = try container.decode(Unions.DeleteReminderResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "deleteRule": if let value = try container.decode(Unions.DeleteRuleResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -10655,10 +10638,6 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.SetFavoriteArticleResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "setFollow": - if let value = try container.decode(Unions.SetFollowResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "setIntegration": if let value = try container.decode(Unions.SetIntegrationResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -10679,14 +10658,6 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.SetRuleResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "setShareArticle": - if let value = try container.decode(Unions.SetShareArticleResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } - case "setShareHighlight": - if let value = try container.decode(Unions.SetShareHighlightResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "setUserPersonalization": if let value = try container.decode(Unions.SetUserPersonalizationResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -10703,34 +10674,26 @@ extension Objects.Mutation: Decodable { if let value = try container.decode(Unions.UnsubscribeResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "updateHighlight": - if let value = try container.decode(Unions.UpdateHighlightResult?.self, forKey: codingKey) { + case "updateEmail": + if let value = try container.decode(Unions.UpdateEmailResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "updateHighlightReply": - if let value = try container.decode(Unions.UpdateHighlightReplyResult?.self, forKey: codingKey) { + case "updateFilter": + if let value = try container.decode(Unions.UpdateFilterResult?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "updateHighlight": + if let value = try container.decode(Unions.UpdateHighlightResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } case "updateLabel": if let value = try container.decode(Unions.UpdateLabelResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "updateLinkShareInfo": - 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) - } - case "updateSharedComment": - if let value = try container.decode(Unions.UpdateSharedCommentResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "updateSubscription": if let value = try container.decode(Unions.UpdateSubscriptionResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -10767,20 +10730,14 @@ extension Objects.Mutation: Decodable { createArticleSavingRequest = map["createArticleSavingRequest"] createGroup = map["createGroup"] createHighlight = map["createHighlight"] - createHighlightReply = map["createHighlightReply"] createLabel = map["createLabel"] createNewsletterEmail = map["createNewsletterEmail"] - createReaction = map["createReaction"] - createReminder = map["createReminder"] deleteAccount = map["deleteAccount"] deleteFilter = map["deleteFilter"] deleteHighlight = map["deleteHighlight"] - deleteHighlightReply = map["deleteHighlightReply"] deleteIntegration = map["deleteIntegration"] deleteLabel = map["deleteLabel"] deleteNewsletterEmail = map["deleteNewsletterEmail"] - deleteReaction = map["deleteReaction"] - deleteReminder = map["deleteReminder"] deleteRule = map["deleteRule"] deleteWebhook = map["deleteWebhook"] generateApiKey = map["generateApiKey"] @@ -10807,25 +10764,20 @@ extension Objects.Mutation: Decodable { setBookmarkArticle = map["setBookmarkArticle"] setDeviceToken = map["setDeviceToken"] setFavoriteArticle = map["setFavoriteArticle"] - setFollow = map["setFollow"] setIntegration = map["setIntegration"] setLabels = map["setLabels"] setLabelsForHighlight = map["setLabelsForHighlight"] setLinkArchived = map["setLinkArchived"] setRule = map["setRule"] - setShareArticle = map["setShareArticle"] - setShareHighlight = map["setShareHighlight"] setUserPersonalization = map["setUserPersonalization"] setWebhook = map["setWebhook"] subscribe = map["subscribe"] unsubscribe = map["unsubscribe"] + updateEmail = map["updateEmail"] + updateFilter = map["updateFilter"] updateHighlight = map["updateHighlight"] - updateHighlightReply = map["updateHighlightReply"] updateLabel = map["updateLabel"] - updateLinkShareInfo = map["updateLinkShareInfo"] updatePage = map["updatePage"] - updateReminder = map["updateReminder"] - updateSharedComment = map["updateSharedComment"] updateSubscription = map["updateSubscription"] updateUser = map["updateUser"] updateUserProfile = map["updateUserProfile"] @@ -10949,25 +10901,6 @@ extension Fields where TypeLock == Objects.Mutation { } } - func createHighlightReply(input: InputObjects.CreateHighlightReplyInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "createHighlightReply", - arguments: [Argument(name: "input", type: "CreateHighlightReplyInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.createHighlightReply[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func createLabel(input: InputObjects.CreateLabelInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "createLabel", @@ -11006,44 +10939,6 @@ extension Fields where TypeLock == Objects.Mutation { } } - func createReaction(input: InputObjects.CreateReactionInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "createReaction", - arguments: [Argument(name: "input", type: "CreateReactionInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.createReaction[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - - func createReminder(input: InputObjects.CreateReminderInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "createReminder", - arguments: [Argument(name: "input", type: "CreateReminderInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.createReminder[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func deleteAccount(userId: String, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "deleteAccount", @@ -11101,25 +10996,6 @@ extension Fields where TypeLock == Objects.Mutation { } } - func deleteHighlightReply(highlightReplyId: String, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "deleteHighlightReply", - arguments: [Argument(name: "highlightReplyId", type: "ID!", value: highlightReplyId)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.deleteHighlightReply[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func deleteIntegration(id: String, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "deleteIntegration", @@ -11177,44 +11053,6 @@ extension Fields where TypeLock == Objects.Mutation { } } - func deleteReaction(id: String, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "deleteReaction", - arguments: [Argument(name: "id", type: "ID!", value: id)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.deleteReaction[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - - func deleteReminder(id: String, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "deleteReminder", - arguments: [Argument(name: "id", type: "ID!", value: id)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.deleteReminder[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func deleteRule(id: String, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "deleteRule", @@ -11709,25 +11547,6 @@ extension Fields where TypeLock == Objects.Mutation { } } - func setFollow(input: InputObjects.SetFollowInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "setFollow", - arguments: [Argument(name: "input", type: "SetFollowInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.setFollow[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func setIntegration(input: InputObjects.SetIntegrationInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "setIntegration", @@ -11823,44 +11642,6 @@ extension Fields where TypeLock == Objects.Mutation { } } - func setShareArticle(input: InputObjects.SetShareArticleInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "setShareArticle", - arguments: [Argument(name: "input", type: "SetShareArticleInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.setShareArticle[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - - func setShareHighlight(input: InputObjects.SetShareHighlightInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "setShareHighlight", - arguments: [Argument(name: "input", type: "SetShareHighlightInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.setShareHighlight[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func setUserPersonalization(input: InputObjects.SetUserPersonalizationInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "setUserPersonalization", @@ -11937,6 +11718,44 @@ extension Fields where TypeLock == Objects.Mutation { } } + func updateEmail(input: InputObjects.UpdateEmailInput, selection: Selection) throws -> Type { + let field = GraphQLField.composite( + name: "updateEmail", + arguments: [Argument(name: "input", type: "UpdateEmailInput!", value: input)], + selection: selection.selection + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.updateEmail[field.alias!] { + return try selection.decode(data: data) + } + throw HttpError.badpayload + case .mocking: + return selection.mock() + } + } + + func updateFilter(input: InputObjects.UpdateFilterInput, selection: Selection) throws -> Type { + let field = GraphQLField.composite( + name: "updateFilter", + arguments: [Argument(name: "input", type: "UpdateFilterInput!", value: input)], + selection: selection.selection + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.updateFilter[field.alias!] { + return try selection.decode(data: data) + } + throw HttpError.badpayload + case .mocking: + return selection.mock() + } + } + func updateHighlight(input: InputObjects.UpdateHighlightInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "updateHighlight", @@ -11956,25 +11775,6 @@ extension Fields where TypeLock == Objects.Mutation { } } - func updateHighlightReply(input: InputObjects.UpdateHighlightReplyInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "updateHighlightReply", - arguments: [Argument(name: "input", type: "UpdateHighlightReplyInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.updateHighlightReply[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func updateLabel(input: InputObjects.UpdateLabelInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "updateLabel", @@ -11994,25 +11794,6 @@ extension Fields where TypeLock == Objects.Mutation { } } - func updateLinkShareInfo(input: InputObjects.UpdateLinkShareInfoInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "updateLinkShareInfo", - arguments: [Argument(name: "input", type: "UpdateLinkShareInfoInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.updateLinkShareInfo[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func updatePage(input: InputObjects.UpdatePageInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "updatePage", @@ -12032,44 +11813,6 @@ extension Fields where TypeLock == Objects.Mutation { } } - func updateReminder(input: InputObjects.UpdateReminderInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "updateReminder", - arguments: [Argument(name: "input", type: "UpdateReminderInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.updateReminder[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - - func updateSharedComment(input: InputObjects.UpdateSharedCommentInput, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "updateSharedComment", - arguments: [Argument(name: "input", type: "UpdateSharedCommentInput!", value: input)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.updateSharedComment[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func updateSubscription(input: InputObjects.UpdateSubscriptionInput, selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "updateSubscription", @@ -12917,7 +12660,7 @@ extension Fields where TypeLock == Objects.Page { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -12926,12 +12669,9 @@ extension Fields where TypeLock == Objects.Page { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } @@ -13271,12 +13011,8 @@ extension Objects { let apiKeys: [String: Unions.ApiKeysResult] let article: [String: Unions.ArticleResult] let articleSavingRequest: [String: Unions.ArticleSavingRequestResult] - 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] @@ -13286,11 +13022,9 @@ extension Objects { let newsletterEmails: [String: Unions.NewsletterEmailsResult] let recentEmails: [String: Unions.RecentEmailsResult] let recentSearches: [String: Unions.RecentSearchesResult] - let reminder: [String: Unions.ReminderResult] let rules: [String: Unions.RulesResult] let search: [String: Unions.SearchResult] let sendInstallInstructions: [String: Unions.SendInstallInstructionsResult] - let sharedArticle: [String: Unions.SharedArticleResult] let subscriptions: [String: Unions.SubscriptionsResult] let typeaheadSearch: [String: Unions.TypeaheadSearchResult] let updatesSince: [String: Unions.UpdatesSinceResult] @@ -13330,30 +13064,14 @@ extension Objects.Query: Decodable { if let value = try container.decode(Unions.ArticleSavingRequestResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "articles": - if let value = try container.decode(Unions.ArticlesResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "deviceTokens": if let value = try container.decode(Unions.DeviceTokensResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "feedArticles": - 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) - } - case "getFollowing": - if let value = try container.decode(Unions.GetFollowingResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "getUserPersonalization": if let value = try container.decode(Unions.GetUserPersonalizationResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -13390,10 +13108,6 @@ extension Objects.Query: Decodable { if let value = try container.decode(Unions.RecentSearchesResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "reminder": - if let value = try container.decode(Unions.ReminderResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "rules": if let value = try container.decode(Unions.RulesResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -13406,10 +13120,6 @@ extension Objects.Query: Decodable { if let value = try container.decode(Unions.SendInstallInstructionsResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "sharedArticle": - if let value = try container.decode(Unions.SharedArticleResult?.self, forKey: codingKey) { - map.set(key: field, hash: alias, value: value as Any) - } case "subscriptions": if let value = try container.decode(Unions.SubscriptionsResult?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -13455,12 +13165,8 @@ extension Objects.Query: Decodable { apiKeys = map["apiKeys"] article = map["article"] articleSavingRequest = map["articleSavingRequest"] - 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"] @@ -13470,11 +13176,9 @@ extension Objects.Query: Decodable { newsletterEmails = map["newsletterEmails"] recentEmails = map["recentEmails"] recentSearches = map["recentSearches"] - reminder = map["reminder"] rules = map["rules"] search = map["search"] sendInstallInstructions = map["sendInstallInstructions"] - sharedArticle = map["sharedArticle"] subscriptions = map["subscriptions"] typeaheadSearch = map["typeaheadSearch"] updatesSince = map["updatesSince"] @@ -13544,25 +13248,6 @@ extension Fields where TypeLock == Objects.Query { } } - func articles(after: OptionalArgument = .absent(), first: OptionalArgument = .absent(), includePending: OptionalArgument = .absent(), query: OptionalArgument = .absent(), sharedOnly: OptionalArgument = .absent(), sort: OptionalArgument = .absent(), selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "articles", - arguments: [Argument(name: "after", type: "String", value: after), Argument(name: "first", type: "Int", value: first), Argument(name: "includePending", type: "Boolean", value: includePending), Argument(name: "query", type: "String", value: query), Argument(name: "sharedOnly", type: "Boolean", value: sharedOnly), Argument(name: "sort", type: "SortParams", value: sort)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.articles[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func deviceTokens(selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "deviceTokens", @@ -13582,25 +13267,6 @@ extension Fields where TypeLock == Objects.Query { } } - func feedArticles(after: OptionalArgument = .absent(), first: OptionalArgument = .absent(), sharedByUser: OptionalArgument = .absent(), sort: OptionalArgument = .absent(), selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "feedArticles", - arguments: [Argument(name: "after", type: "String", value: after), Argument(name: "first", type: "Int", value: first), Argument(name: "sharedByUser", type: "ID", value: sharedByUser), Argument(name: "sort", type: "SortParams", value: sort)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.feedArticles[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func filters(selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "filters", @@ -13620,44 +13286,6 @@ extension Fields where TypeLock == Objects.Query { } } - func getFollowers(userId: OptionalArgument = .absent(), selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "getFollowers", - arguments: [Argument(name: "userId", type: "ID", value: userId)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.getFollowers[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - - func getFollowing(userId: OptionalArgument = .absent(), selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "getFollowing", - arguments: [Argument(name: "userId", type: "ID", value: userId)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.getFollowing[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func getUserPersonalization(selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "getUserPersonalization", @@ -13822,25 +13450,6 @@ extension Fields where TypeLock == Objects.Query { } } - func reminder(linkId: String, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "reminder", - arguments: [Argument(name: "linkId", type: "ID!", value: linkId)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.reminder[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func rules(enabled: OptionalArgument = .absent(), selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "rules", @@ -13898,25 +13507,6 @@ extension Fields where TypeLock == Objects.Query { } } - func sharedArticle(selectedHighlightId: OptionalArgument = .absent(), slug: String, username: String, selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "sharedArticle", - arguments: [Argument(name: "selectedHighlightId", type: "String", value: selectedHighlightId), Argument(name: "slug", type: "String!", value: slug), Argument(name: "username", type: "String!", value: username)], - selection: selection.selection - ) - select(field) - - switch response { - case let .decoding(data): - if let data = data.sharedArticle[field.alias!] { - return try selection.decode(data: data) - } - throw HttpError.badpayload - case .mocking: - return selection.mock() - } - } - func subscriptions(sort: OptionalArgument = .absent(), type: OptionalArgument = .absent(), selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "subscriptions", @@ -15662,7 +15252,7 @@ extension Fields where TypeLock == Objects.RecommendationGroup { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -15671,12 +15261,9 @@ extension Fields where TypeLock == Objects.RecommendationGroup { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } } @@ -16494,7 +16081,7 @@ extension Fields where TypeLock == Objects.Rule { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -16503,12 +16090,9 @@ extension Fields where TypeLock == Objects.Rule { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } } @@ -18776,7 +18360,7 @@ extension Selection where TypeLock == Never, Type == Never { extension Objects { struct SetFavoriteArticleSuccess { let __typename: TypeName = .setFavoriteArticleSuccess - let favoriteArticle: [String: Objects.Article] + let success: [String: Bool] enum TypeName: String, Codable { case setFavoriteArticleSuccess = "SetFavoriteArticleSuccess" @@ -18796,8 +18380,8 @@ extension Objects.SetFavoriteArticleSuccess: Decodable { let field = GraphQLField.getFieldNameFromAlias(alias) switch field { - case "favoriteArticle": - if let value = try container.decode(Objects.Article?.self, forKey: codingKey) { + case "success": + if let value = try container.decode(Bool?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } default: @@ -18810,27 +18394,26 @@ extension Objects.SetFavoriteArticleSuccess: Decodable { } } - favoriteArticle = map["favoriteArticle"] + success = map["success"] } } extension Fields where TypeLock == Objects.SetFavoriteArticleSuccess { - func favoriteArticle(selection: Selection) throws -> Type { - let field = GraphQLField.composite( - name: "favoriteArticle", - arguments: [], - selection: selection.selection + func success() throws -> Bool { + let field = GraphQLField.leaf( + name: "success", + arguments: [] ) select(field) switch response { case let .decoding(data): - if let data = data.favoriteArticle[field.alias!] { - return try selection.decode(data: data) + if let data = data.success[field.alias!] { + return data } throw HttpError.badpayload case .mocking: - return selection.mock() + return Bool.mockValue } } } @@ -20623,7 +20206,7 @@ extension Fields where TypeLock == Objects.Subscription { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -20632,12 +20215,9 @@ extension Fields where TypeLock == Objects.Subscription { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } @@ -21347,6 +20927,288 @@ extension Selection where TypeLock == Never, Type == Never { typealias UnsubscribeSuccess = Selection } +extension Objects { + struct UpdateEmailError { + let __typename: TypeName = .updateEmailError + let errorCodes: [String: [Enums.UpdateEmailErrorCode]] + + enum TypeName: String, Codable { + case updateEmailError = "UpdateEmailError" + } + } +} + +extension Objects.UpdateEmailError: 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.UpdateEmailErrorCode]?.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.UpdateEmailError { + func errorCodes() throws -> [Enums.UpdateEmailErrorCode] { + 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 UpdateEmailError = Selection +} + +extension Objects { + struct UpdateEmailSuccess { + let __typename: TypeName = .updateEmailSuccess + let email: [String: String] + let verificationEmailSent: [String: Bool] + + enum TypeName: String, Codable { + case updateEmailSuccess = "UpdateEmailSuccess" + } + } +} + +extension Objects.UpdateEmailSuccess: 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 "email": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "verificationEmailSent": + if let value = try container.decode(Bool?.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)." + ) + ) + } + } + + email = map["email"] + verificationEmailSent = map["verificationEmailSent"] + } +} + +extension Fields where TypeLock == Objects.UpdateEmailSuccess { + func email() throws -> String { + let field = GraphQLField.leaf( + name: "email", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.email[field.alias!] { + return data + } + throw HttpError.badpayload + case .mocking: + return String.mockValue + } + } + + func verificationEmailSent() throws -> Bool? { + let field = GraphQLField.leaf( + name: "verificationEmailSent", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.verificationEmailSent[field.alias!] + case .mocking: + return nil + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias UpdateEmailSuccess = Selection +} + +extension Objects { + struct UpdateFilterError { + let __typename: TypeName = .updateFilterError + let errorCodes: [String: [Enums.UpdateFilterErrorCode]] + + enum TypeName: String, Codable { + case updateFilterError = "UpdateFilterError" + } + } +} + +extension Objects.UpdateFilterError: 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.UpdateFilterErrorCode]?.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.UpdateFilterError { + func errorCodes() throws -> [Enums.UpdateFilterErrorCode] { + 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 UpdateFilterError = Selection +} + +extension Objects { + struct UpdateFilterSuccess { + let __typename: TypeName = .updateFilterSuccess + let filter: [String: Objects.Filter] + + enum TypeName: String, Codable { + case updateFilterSuccess = "UpdateFilterSuccess" + } + } +} + +extension Objects.UpdateFilterSuccess: 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.UpdateFilterSuccess { + 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 UpdateFilterSuccess = Selection +} + extension Objects { struct UpdateHighlightError { let __typename: TypeName = .updateHighlightError @@ -23158,6 +23020,7 @@ extension Selection where TypeLock == Never, Type == Never { extension Objects { struct User { let __typename: TypeName = .user + let email: [String: String] let followersCount: [String: Int] let friendsCount: [String: Int] let id: [String: String] @@ -23170,6 +23033,7 @@ extension Objects { let sharedArticlesCount: [String: Int] let sharedHighlightsCount: [String: Int] let sharedNotesCount: [String: Int] + let source: [String: String] let viewerIsFollowing: [String: Bool] enum TypeName: String, Codable { @@ -23190,6 +23054,10 @@ extension Objects.User: Decodable { let field = GraphQLField.getFieldNameFromAlias(alias) switch field { + case "email": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "followersCount": if let value = try container.decode(Int?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -23238,6 +23106,10 @@ extension Objects.User: Decodable { if let value = try container.decode(Int?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "source": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "viewerIsFollowing": if let value = try container.decode(Bool?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -23252,6 +23124,7 @@ extension Objects.User: Decodable { } } + email = map["email"] followersCount = map["followersCount"] friendsCount = map["friendsCount"] id = map["id"] @@ -23264,11 +23137,27 @@ extension Objects.User: Decodable { sharedArticlesCount = map["sharedArticlesCount"] sharedHighlightsCount = map["sharedHighlightsCount"] sharedNotesCount = map["sharedNotesCount"] + source = map["source"] viewerIsFollowing = map["viewerIsFollowing"] } } extension Fields where TypeLock == Objects.User { + func email() throws -> String? { + let field = GraphQLField.leaf( + name: "email", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.email[field.alias!] + case .mocking: + return nil + } + } + func followersCount() throws -> Int? { let field = GraphQLField.leaf( name: "followersCount", @@ -23464,6 +23353,21 @@ extension Fields where TypeLock == Objects.User { } } + func source() throws -> String? { + let field = GraphQLField.leaf( + name: "source", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.source[field.alias!] + case .mocking: + return nil + } + } + func viewerIsFollowing() throws -> Bool? { let field = GraphQLField.leaf( name: "viewerIsFollowing", @@ -24210,7 +24114,7 @@ extension Fields where TypeLock == Objects.Webhook { } } - func updatedAt() throws -> DateTime { + func updatedAt() throws -> DateTime? { let field = GraphQLField.leaf( name: "updatedAt", arguments: [] @@ -24219,12 +24123,9 @@ extension Fields where TypeLock == Objects.Webhook { switch response { case let .decoding(data): - if let data = data.updatedAt[field.alias!] { - return data - } - throw HttpError.badpayload + return data.updatedAt[field.alias!] case .mocking: - return DateTime.mockValue + return nil } } @@ -29240,7 +29141,7 @@ extension Unions { struct SetFavoriteArticleResult { let __typename: TypeName let errorCodes: [String: [Enums.SetFavoriteArticleErrorCode]] - let favoriteArticle: [String: Objects.Article] + let success: [String: Bool] enum TypeName: String, Codable { case setFavoriteArticleError = "SetFavoriteArticleError" @@ -29265,8 +29166,8 @@ extension Unions.SetFavoriteArticleResult: Decodable { if let value = try container.decode([Enums.SetFavoriteArticleErrorCode]?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } - case "favoriteArticle": - if let value = try container.decode(Objects.Article?.self, forKey: codingKey) { + case "success": + if let value = try container.decode(Bool?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } default: @@ -29282,7 +29183,7 @@ extension Unions.SetFavoriteArticleResult: Decodable { __typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!) errorCodes = map["errorCodes"] - favoriteArticle = map["favoriteArticle"] + success = map["success"] } } @@ -29297,7 +29198,7 @@ extension Fields where TypeLock == Unions.SetFavoriteArticleResult { let data = Objects.SetFavoriteArticleError(errorCodes: data.errorCodes) return try setFavoriteArticleError.decode(data: data) case .setFavoriteArticleSuccess: - let data = Objects.SetFavoriteArticleSuccess(favoriteArticle: data.favoriteArticle) + let data = Objects.SetFavoriteArticleSuccess(success: data.success) return try setFavoriteArticleSuccess.decode(data: data) } case .mocking: @@ -30284,6 +30185,160 @@ extension Selection where TypeLock == Never, Type == Never { typealias UnsubscribeResult = Selection } +extension Unions { + struct UpdateEmailResult { + let __typename: TypeName + let email: [String: String] + let errorCodes: [String: [Enums.UpdateEmailErrorCode]] + let verificationEmailSent: [String: Bool] + + enum TypeName: String, Codable { + case updateEmailError = "UpdateEmailError" + case updateEmailSuccess = "UpdateEmailSuccess" + } + } +} + +extension Unions.UpdateEmailResult: 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 "email": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "errorCodes": + if let value = try container.decode([Enums.UpdateEmailErrorCode]?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "verificationEmailSent": + if let value = try container.decode(Bool?.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")!) + + email = map["email"] + errorCodes = map["errorCodes"] + verificationEmailSent = map["verificationEmailSent"] + } +} + +extension Fields where TypeLock == Unions.UpdateEmailResult { + func on(updateEmailError: Selection, updateEmailSuccess: Selection) throws -> Type { + select([GraphQLField.fragment(type: "UpdateEmailError", selection: updateEmailError.selection), GraphQLField.fragment(type: "UpdateEmailSuccess", selection: updateEmailSuccess.selection)]) + + switch response { + case let .decoding(data): + switch data.__typename { + case .updateEmailError: + let data = Objects.UpdateEmailError(errorCodes: data.errorCodes) + return try updateEmailError.decode(data: data) + case .updateEmailSuccess: + let data = Objects.UpdateEmailSuccess(email: data.email, verificationEmailSent: data.verificationEmailSent) + return try updateEmailSuccess.decode(data: data) + } + case .mocking: + return updateEmailError.mock() + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias UpdateEmailResult = Selection +} + +extension Unions { + struct UpdateFilterResult { + let __typename: TypeName + let errorCodes: [String: [Enums.UpdateFilterErrorCode]] + let filter: [String: Objects.Filter] + + enum TypeName: String, Codable { + case updateFilterError = "UpdateFilterError" + case updateFilterSuccess = "UpdateFilterSuccess" + } + } +} + +extension Unions.UpdateFilterResult: 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.UpdateFilterErrorCode]?.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.UpdateFilterResult { + func on(updateFilterError: Selection, updateFilterSuccess: Selection) throws -> Type { + select([GraphQLField.fragment(type: "UpdateFilterError", selection: updateFilterError.selection), GraphQLField.fragment(type: "UpdateFilterSuccess", selection: updateFilterSuccess.selection)]) + + switch response { + case let .decoding(data): + switch data.__typename { + case .updateFilterError: + let data = Objects.UpdateFilterError(errorCodes: data.errorCodes) + return try updateFilterError.decode(data: data) + case .updateFilterSuccess: + let data = Objects.UpdateFilterSuccess(filter: data.filter) + return try updateFilterSuccess.decode(data: data) + } + case .mocking: + return updateFilterError.mock() + } + } +} + +extension Selection where TypeLock == Never, Type == Never { + typealias UpdateFilterResult = Selection +} + extension Unions { struct UpdateHighlightReplyResult { let __typename: TypeName @@ -32584,6 +32639,28 @@ extension Enums { } } +extension Enums { + /// UpdateEmailErrorCode + enum UpdateEmailErrorCode: String, CaseIterable, Codable { + case badRequest = "BAD_REQUEST" + + case emailAlreadyExists = "EMAIL_ALREADY_EXISTS" + + case unauthorized = "UNAUTHORIZED" + } +} + +extension Enums { + /// UpdateFilterErrorCode + enum UpdateFilterErrorCode: String, CaseIterable, Codable { + case badRequest = "BAD_REQUEST" + + case notFound = "NOT_FOUND" + + case unauthorized = "UNAUTHORIZED" + } +} + extension Enums { /// UpdateHighlightErrorCode enum UpdateHighlightErrorCode: String, CaseIterable, Codable { @@ -33542,9 +33619,11 @@ extension InputObjects { extension InputObjects { struct SaveArticleReadingProgressInput: Encodable, Hashable { + var force: OptionalArgument = .absent() + var id: String - var readingProgressAnchorIndex: Int + var readingProgressAnchorIndex: OptionalArgument = .absent() var readingProgressPercent: Double @@ -33552,13 +33631,15 @@ extension InputObjects { func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) + if force.hasValue { try container.encode(force, forKey: .force) } try container.encode(id, forKey: .id) - try container.encode(readingProgressAnchorIndex, forKey: .readingProgressAnchorIndex) + if readingProgressAnchorIndex.hasValue { try container.encode(readingProgressAnchorIndex, forKey: .readingProgressAnchorIndex) } try container.encode(readingProgressPercent, forKey: .readingProgressPercent) if readingProgressTopPercent.hasValue { try container.encode(readingProgressTopPercent, forKey: .readingProgressTopPercent) } } enum CodingKeys: String, CodingKey { + case force case id case readingProgressAnchorIndex case readingProgressPercent @@ -33604,31 +33685,31 @@ extension InputObjects { extension InputObjects { struct SaveFilterInput: Encodable, Hashable { - var category: String + var category: OptionalArgument = .absent() var description: OptionalArgument = .absent() var filter: String - var id: OptionalArgument = .absent() - var name: String + var position: OptionalArgument = .absent() + func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(category, forKey: .category) + if category.hasValue { try container.encode(category, forKey: .category) } 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) + if position.hasValue { try container.encode(position, forKey: .position) } } enum CodingKeys: String, CodingKey { case category case description case filter - case id case name + case position } } } @@ -34061,27 +34142,77 @@ extension InputObjects { extension InputObjects { struct SubscribeInput: Encodable, Hashable { - var name: OptionalArgument = .absent() - var subscriptionType: OptionalArgument = .absent() - var url: OptionalArgument = .absent() + var url: String func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - if name.hasValue { try container.encode(name, forKey: .name) } if subscriptionType.hasValue { try container.encode(subscriptionType, forKey: .subscriptionType) } - if url.hasValue { try container.encode(url, forKey: .url) } + try container.encode(url, forKey: .url) } enum CodingKeys: String, CodingKey { - case name case subscriptionType case url } } } +extension InputObjects { + struct UpdateEmailInput: Encodable, Hashable { + var email: String + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(email, forKey: .email) + } + + enum CodingKeys: String, CodingKey { + case email + } + } +} + +extension InputObjects { + struct UpdateFilterInput: Encodable, Hashable { + var category: OptionalArgument = .absent() + + var description: OptionalArgument = .absent() + + var filter: OptionalArgument = .absent() + + var id: String + + var name: OptionalArgument = .absent() + + var position: OptionalArgument = .absent() + + var visible: OptionalArgument = .absent() + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + if category.hasValue { try container.encode(category, forKey: .category) } + if description.hasValue { try container.encode(description, forKey: .description) } + if filter.hasValue { try container.encode(filter, forKey: .filter) } + try container.encode(id, forKey: .id) + if name.hasValue { try container.encode(name, forKey: .name) } + if position.hasValue { try container.encode(position, forKey: .position) } + if visible.hasValue { try container.encode(visible, forKey: .visible) } + } + + enum CodingKeys: String, CodingKey { + case category + case description + case filter + case id + case name + case position + case visible + } + } +} + extension InputObjects { struct UpdateHighlightInput: Encodable, Hashable { var annotation: OptionalArgument = .absent() @@ -34283,8 +34414,12 @@ extension InputObjects { var lastFetchedAt: OptionalArgument = .absent() + var lastFetchedChecksum: OptionalArgument = .absent() + var name: OptionalArgument = .absent() + var scheduledAt: OptionalArgument = .absent() + var status: OptionalArgument = .absent() func encode(to encoder: Encoder) throws { @@ -34292,7 +34427,9 @@ extension InputObjects { if description.hasValue { try container.encode(description, forKey: .description) } try container.encode(id, forKey: .id) if lastFetchedAt.hasValue { try container.encode(lastFetchedAt, forKey: .lastFetchedAt) } + if lastFetchedChecksum.hasValue { try container.encode(lastFetchedChecksum, forKey: .lastFetchedChecksum) } if name.hasValue { try container.encode(name, forKey: .name) } + if scheduledAt.hasValue { try container.encode(scheduledAt, forKey: .scheduledAt) } if status.hasValue { try container.encode(status, forKey: .status) } } @@ -34300,7 +34437,9 @@ extension InputObjects { case description case id case lastFetchedAt + case lastFetchedChecksum case name + case scheduledAt case status } } diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/CreateReminder.swift b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/CreateReminder.swift index f7ad4d475..8b1378917 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/CreateReminder.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/CreateReminder.swift @@ -1,79 +1 @@ -import Foundation -import Models -import SwiftGraphQL -public enum ReminderItemId { - case clientRequest(id: String) - case link(id: String) - - var linkId: String? { - switch self { - case .clientRequest: - return nil - case let .link(id): - return id - } - } - - var clientRequestId: String? { - switch self { - case .link: - return nil - case let .clientRequest(id): - return id - } - } -} - -public extension DataService { - func createReminder( - reminderItemId: ReminderItemId, - remindAt: Date - ) async throws { - enum MutationResult { - case complete(id: String) - case error(errorCode: Enums.CreateReminderErrorCode) - } - - let selection = Selection { - try $0.on( - createReminderError: .init { .error(errorCode: try $0.errorCodes().first ?? .badRequest) }, - createReminderSuccess: .init { - .complete(id: try $0.reminder(selection: Selection.Reminder { try $0.id() })) - } - ) - } - - let mutation = Selection.Mutation { - try $0.createReminder( - input: InputObjects.CreateReminderInput( - archiveUntil: true, - clientRequestId: OptionalArgument(reminderItemId.clientRequestId), - linkId: OptionalArgument(reminderItemId.linkId), - remindAt: DateTime(from: remindAt), - sendNotification: true - ), - selection: selection - ) - } - - let path = appEnvironment.graphqlPath - let headers = networker.defaultHeaders - - return try await withCheckedThrowingContinuation { continuation in - send(mutation, to: path, headers: headers) { queryResult in - guard let payload = try? queryResult.get() else { - continuation.resume(throwing: BasicError.message(messageText: "network error")) - return - } - - switch payload.data { - case .complete: - continuation.resume() - case let .error(errorCode: errorCode): - continuation.resume(throwing: BasicError.message(messageText: errorCode.rawValue)) - } - } - } - } -} diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleReadingProgress.swift b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleReadingProgress.swift index 41781b70e..100109009 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleReadingProgress.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleReadingProgress.swift @@ -4,13 +4,15 @@ import Models import SwiftGraphQL extension DataService { - public func updateLinkReadingProgress(itemID: String, readingProgress: Double, anchorIndex: Int) { + public func updateLinkReadingProgress(itemID: String, readingProgress: Double, anchorIndex: Int, force: Bool?) { backgroundContext.perform { [weak self] in guard let self = self else { return } guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: self.backgroundContext) else { return } - if readingProgress != 0, readingProgress < linkedItem.readingProgress { - return + if let force = force, !force { + if readingProgress != 0, readingProgress < linkedItem.readingProgress { + return + } } print("updating reading progress: ", readingProgress, anchorIndex) @@ -24,12 +26,13 @@ extension DataService { self.syncLinkReadingProgress( itemID: linkedItem.unwrappedID, readingProgress: readingProgress, - anchorIndex: anchorIndex + anchorIndex: anchorIndex, + force: force ) } } - func syncLinkReadingProgress(itemID: String, readingProgress: Double, anchorIndex: Int) { + func syncLinkReadingProgress(itemID: String, readingProgress: Double, anchorIndex: Int, force: Bool?) { enum MutationResult { case saved(readAt: Date?) case error(errorCode: Enums.SaveArticleReadingProgressErrorCode) @@ -49,8 +52,9 @@ extension DataService { let mutation = Selection.Mutation { try $0.saveArticleReadingProgress( input: InputObjects.SaveArticleReadingProgressInput( + force: OptionalArgument(force), id: itemID, - readingProgressAnchorIndex: anchorIndex, + readingProgressAnchorIndex: OptionalArgument(anchorIndex), readingProgressPercent: readingProgress ), selection: selection diff --git a/apple/OmnivoreKit/Sources/Services/DataService/OfflineSync.swift b/apple/OmnivoreKit/Sources/Services/DataService/OfflineSync.swift index 7c2b94693..6f50cbd8d 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/OfflineSync.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/OfflineSync.swift @@ -154,7 +154,8 @@ public extension DataService { syncLinkReadingProgress( itemID: item.unwrappedID, readingProgress: item.readingProgress, - anchorIndex: Int(item.readingProgressAnchor) + anchorIndex: Int(item.readingProgressAnchor), + force: item.isPDF ) } } diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Queries/ArticleContentQuery.swift b/apple/OmnivoreKit/Sources/Services/DataService/Queries/ArticleContentQuery.swift index a1427b35a..f654003f3 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Queries/ArticleContentQuery.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Queries/ArticleContentQuery.swift @@ -26,7 +26,7 @@ extension DataService { createdAt: try $0.createdAt().value ?? Date(), savedAt: try $0.savedAt().value ?? Date(), readAt: try $0.readAt()?.value, - updatedAt: try $0.updatedAt().value ?? Date(), + updatedAt: try $0.updatedAt()?.value ?? Date(), state: try $0.state()?.rawValue.asArticleContentStatus ?? .succeeded, readingProgress: try $0.readingProgressPercent(), readingProgressAnchor: try $0.readingProgressAnchorIndex(), diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Queries/LinkedItemNetworkQuery.swift b/apple/OmnivoreKit/Sources/Services/DataService/Queries/LinkedItemNetworkQuery.swift index 548ba02ea..9c1dd7a98 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Queries/LinkedItemNetworkQuery.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Queries/LinkedItemNetworkQuery.swift @@ -258,7 +258,7 @@ private let libraryArticleSelection = Selection.Article { createdAt: try $0.createdAt().value ?? Date(), savedAt: try $0.savedAt().value ?? Date(), readAt: try $0.readAt()?.value, - updatedAt: try $0.updatedAt().value ?? Date(), + updatedAt: try $0.updatedAt()?.value ?? Date(), state: try $0.state()?.rawValue.asArticleContentStatus ?? .succeeded, readingProgress: try $0.readingProgressPercent(), readingProgressAnchor: try $0.readingProgressAnchorIndex(), diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Queries/SubscriptionsQuery.swift b/apple/OmnivoreKit/Sources/Services/DataService/Queries/SubscriptionsQuery.swift index a78045904..17ee2d565 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Queries/SubscriptionsQuery.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Queries/SubscriptionsQuery.swift @@ -19,7 +19,7 @@ public extension DataService { status: try SubscriptionStatus.make(from: $0.status()), unsubscribeHttpUrl: try $0.unsubscribeHttpUrl(), unsubscribeMailTo: try $0.unsubscribeMailTo(), - updatedAt: try $0.updatedAt().value, + updatedAt: try $0.updatedAt()?.value ?? Date(), url: try $0.url(), icon: try $0.icon() ) diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Selections/HighlightSelection.swift b/apple/OmnivoreKit/Sources/Services/DataService/Selections/HighlightSelection.swift index b9e9e53f8..52e733239 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Selections/HighlightSelection.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Selections/HighlightSelection.swift @@ -1,3 +1,4 @@ +import Foundation import Models import SwiftGraphQL @@ -22,7 +23,7 @@ let highlightSelection = Selection.Highlight { patch: try $0.patch() ?? "", annotation: try $0.annotation(), createdAt: try $0.createdAt().value, - updatedAt: try $0.updatedAt().value, + updatedAt: try $0.updatedAt()?.value ?? Date(), createdByMe: try $0.createdByMe(), createdBy: try $0.user(selection: userProfileSelection), positionPercent: try $0.highlightPositionPercent(),