From e20424ff1b7c39eb71ff060f7759e69ca46500d5 Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 19 Dec 2023 10:26:48 +0800 Subject: [PATCH] Subscriptions UX --- .../App/Views/Profile/Subscriptions.swift | 24 ++- .../Services/DataService/GQLSchema.swift | 182 +++++++++++++++++- .../Selections/SubsciptionSelection.swift | 4 +- 3 files changed, 199 insertions(+), 11 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift b/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift index 627975482..6afca2f24 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Profile/Subscriptions.swift @@ -327,6 +327,7 @@ struct SubscriptionSettingsView: View { @State var prefetchContent = false @State var deleteConfirmationShown = false @State var showDeleteCompleted = false + @State var folderSelection: String = "" let dismiss: () -> Void let unsubscribe: (_: Subscription) -> Void @@ -355,14 +356,23 @@ struct SubscriptionSettingsView: View { .padding(.horizontal, 15) List { - Toggle(isOn: $prefetchContent, label: { Text("Prefetch Content:").foregroundColor(.appGrayText) }) + Toggle(isOn: $prefetchContent, label: { Text("Prefetch Content:") }) + .onAppear { + prefetchContent = subscription.fetchContent + } HStack { - Text("Destination Folder:") - .foregroundColor(.appGrayText) - Spacer() - Menu(content: {}, label: { - Text("Following <>") - }) + Picker("Destination Folder", selection: $folderSelection) { + Text("Inbox").tag("inbox") + Text("Following").tag("following") + } + .pickerStyle(MenuPickerStyle()) // makes the picker appear as a menu + .onAppear { + folderSelection = subscription.folder + print("FOLDER: ", folderSelection) + } + .onChange(of: folderSelection) { _ in + print("CHANGED FOLDER: ", folderSelection) + } } }.listStyle(.insetGrouped) diff --git a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift index d417292ca..71ce9f54b 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/GQLSchema.swift @@ -9220,6 +9220,7 @@ extension Objects { let `internal`: [String: Bool] let name: [String: String] let position: [String: Int] + let source: [String: String] enum TypeName: String, Codable { case label = "Label" @@ -9267,6 +9268,10 @@ extension Objects.Label: 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) + } default: throw DecodingError.dataCorrupted( DecodingError.Context( @@ -9284,6 +9289,7 @@ extension Objects.Label: Decodable { self.internal = map["internal"] name = map["name"] position = map["position"] + source = map["source"] } } @@ -9401,6 +9407,21 @@ extension Fields where TypeLock == Objects.Label { return nil } } + + 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 + } + } } extension Selection where TypeLock == Never, Type == Never { @@ -11601,10 +11622,10 @@ extension Fields where TypeLock == Objects.Mutation { } } - func createNewsletterEmail(selection: Selection) throws -> Type { + func createNewsletterEmail(input: OptionalArgument = .absent(), selection: Selection) throws -> Type { let field = GraphQLField.composite( name: "createNewsletterEmail", - arguments: [], + arguments: [Argument(name: "input", type: "CreateNewsletterEmailInput", value: input)], selection: selection.selection ) select(field) @@ -12619,7 +12640,10 @@ extension Objects { let address: [String: String] let confirmationCode: [String: String] let createdAt: [String: DateTime] + let description: [String: String] + let folder: [String: String] let id: [String: String] + let name: [String: String] let subscriptionCount: [String: Int] enum TypeName: String, Codable { @@ -12652,10 +12676,22 @@ extension Objects.NewsletterEmail: Decodable { if let value = try container.decode(DateTime?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "description": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "folder": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "id": if let value = try container.decode(String?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "name": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "subscriptionCount": if let value = try container.decode(Int?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -12673,7 +12709,10 @@ extension Objects.NewsletterEmail: Decodable { address = map["address"] confirmationCode = map["confirmationCode"] createdAt = map["createdAt"] + description = map["description"] + folder = map["folder"] id = map["id"] + name = map["name"] subscriptionCount = map["subscriptionCount"] } } @@ -12730,6 +12769,39 @@ extension Fields where TypeLock == Objects.NewsletterEmail { } } + func description() throws -> String? { + let field = GraphQLField.leaf( + name: "description", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.description[field.alias!] + case .mocking: + return nil + } + } + + func folder() throws -> String { + let field = GraphQLField.leaf( + name: "folder", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.folder[field.alias!] { + return data + } + throw HttpError.badpayload + case .mocking: + return String.mockValue + } + } + func id() throws -> String { let field = GraphQLField.leaf( name: "id", @@ -12748,6 +12820,21 @@ extension Fields where TypeLock == Objects.NewsletterEmail { } } + func name() throws -> String? { + let field = GraphQLField.leaf( + name: "name", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + return data.name[field.alias!] + case .mocking: + return nil + } + } + func subscriptionCount() throws -> Int { let field = GraphQLField.leaf( name: "subscriptionCount", @@ -20863,6 +20950,8 @@ extension Objects { let count: [String: Int] let createdAt: [String: DateTime] let description: [String: String] + let fetchContent: [String: Bool] + let folder: [String: String] let icon: [String: String] let id: [String: String] let isPrivate: [String: Bool] @@ -20910,6 +20999,14 @@ extension Objects.Subscription: Decodable { if let value = try container.decode(String?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) } + case "fetchContent": + if let value = try container.decode(Bool?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } + case "folder": + if let value = try container.decode(String?.self, forKey: codingKey) { + map.set(key: field, hash: alias, value: value as Any) + } case "icon": if let value = try container.decode(String?.self, forKey: codingKey) { map.set(key: field, hash: alias, value: value as Any) @@ -20972,6 +21069,8 @@ extension Objects.Subscription: Decodable { count = map["count"] createdAt = map["createdAt"] description = map["description"] + fetchContent = map["fetchContent"] + folder = map["folder"] icon = map["icon"] id = map["id"] isPrivate = map["isPrivate"] @@ -21054,6 +21153,42 @@ extension Fields where TypeLock == Objects.Subscription { } } + func fetchContent() throws -> Bool { + let field = GraphQLField.leaf( + name: "fetchContent", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.fetchContent[field.alias!] { + return data + } + throw HttpError.badpayload + case .mocking: + return Bool.mockValue + } + } + + func folder() throws -> String { + let field = GraphQLField.leaf( + name: "folder", + arguments: [] + ) + select(field) + + switch response { + case let .decoding(data): + if let data = data.folder[field.alias!] { + return data + } + throw HttpError.badpayload + case .mocking: + return String.mockValue + } + } + func icon() throws -> String? { let field = GraphQLField.leaf( name: "icon", @@ -34483,6 +34618,29 @@ extension InputObjects { } } +extension InputObjects { + struct CreateNewsletterEmailInput: Encodable, Hashable { + var description: OptionalArgument = .absent() + + var folder: OptionalArgument = .absent() + + var name: OptionalArgument = .absent() + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + if description.hasValue { try container.encode(description, forKey: .description) } + if folder.hasValue { try container.encode(folder, forKey: .folder) } + if name.hasValue { try container.encode(name, forKey: .name) } + } + + enum CodingKeys: String, CodingKey { + case description + case folder + case name + } + } +} + extension InputObjects { struct CreateReactionInput: Encodable, Hashable { var code: Enums.ReactionType @@ -35347,17 +35505,21 @@ extension InputObjects { var pageId: String + var source: OptionalArgument = .absent() + func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) if labelIds.hasValue { try container.encode(labelIds, forKey: .labelIds) } if labels.hasValue { try container.encode(labels, forKey: .labels) } try container.encode(pageId, forKey: .pageId) + if source.hasValue { try container.encode(source, forKey: .source) } } enum CodingKeys: String, CodingKey { case labelIds case labels case pageId + case source } } } @@ -35560,6 +35722,10 @@ extension InputObjects { struct SubscribeInput: Encodable, Hashable { var autoAddToLibrary: OptionalArgument = .absent() + var fetchContent: OptionalArgument = .absent() + + var folder: OptionalArgument = .absent() + var isPrivate: OptionalArgument = .absent() var subscriptionType: OptionalArgument = .absent() @@ -35569,6 +35735,8 @@ extension InputObjects { func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) if autoAddToLibrary.hasValue { try container.encode(autoAddToLibrary, forKey: .autoAddToLibrary) } + if fetchContent.hasValue { try container.encode(fetchContent, forKey: .fetchContent) } + if folder.hasValue { try container.encode(folder, forKey: .folder) } if isPrivate.hasValue { try container.encode(isPrivate, forKey: .isPrivate) } if subscriptionType.hasValue { try container.encode(subscriptionType, forKey: .subscriptionType) } try container.encode(url, forKey: .url) @@ -35576,6 +35744,8 @@ extension InputObjects { enum CodingKeys: String, CodingKey { case autoAddToLibrary + case fetchContent + case folder case isPrivate case subscriptionType case url @@ -35840,6 +36010,10 @@ extension InputObjects { var description: OptionalArgument = .absent() + var fetchContent: OptionalArgument = .absent() + + var folder: OptionalArgument = .absent() + var id: String var isPrivate: OptionalArgument = .absent() @@ -35858,6 +36032,8 @@ extension InputObjects { var container = encoder.container(keyedBy: CodingKeys.self) if autoAddToLibrary.hasValue { try container.encode(autoAddToLibrary, forKey: .autoAddToLibrary) } if description.hasValue { try container.encode(description, forKey: .description) } + if fetchContent.hasValue { try container.encode(fetchContent, forKey: .fetchContent) } + if folder.hasValue { try container.encode(folder, forKey: .folder) } try container.encode(id, forKey: .id) if isPrivate.hasValue { try container.encode(isPrivate, forKey: .isPrivate) } if lastFetchedAt.hasValue { try container.encode(lastFetchedAt, forKey: .lastFetchedAt) } @@ -35870,6 +36046,8 @@ extension InputObjects { enum CodingKeys: String, CodingKey { case autoAddToLibrary case description + case fetchContent + case folder case id case isPrivate case lastFetchedAt diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Selections/SubsciptionSelection.swift b/apple/OmnivoreKit/Sources/Services/DataService/Selections/SubsciptionSelection.swift index 7df09b519..f8e883e97 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Selections/SubsciptionSelection.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Selections/SubsciptionSelection.swift @@ -10,8 +10,8 @@ let subscriptionSelection = Selection.Subscription { subscriptionID: try $0.id(), name: try $0.name(), type: try SubscriptionType.from($0.type()), - folder: try $0.folder() ?? "inbox", - fetchContent: try $0.fetchContent() ?? true, + folder: try $0.folder(), + fetchContent: try $0.fetchContent(), newsletterEmailAddress: try $0.newsletterEmail(), status: try SubscriptionStatus.make(from: $0.status()), unsubscribeHttpUrl: try $0.unsubscribeHttpUrl(),