Add toggle for including highlights

This commit is contained in:
Jackson Harper
2022-12-08 16:20:04 +08:00
parent 447458f6be
commit 9d9f2f3be9
4 changed files with 305 additions and 21 deletions

View File

@ -12,11 +12,14 @@ import Views
@Published var showError = false
@Published var showNoteView = false
@Published var note: String = ""
@Published var withHighlights: Bool = true
let pageID: String
let highlightCount: Int
init(pageID: String) {
init(pageID: String, highlightCount: Int) {
self.pageID = pageID
self.highlightCount = highlightCount
}
func loadGroups(dataService: DataService) async {
@ -36,7 +39,10 @@ import Views
isRunning = true
do {
try await dataService.recommendPage(pageID: pageID, groupIDs: selectedGroups.map(\.id), note: note.isEmpty ? nil : note)
try await dataService.recommendPage(pageID: pageID,
groupIDs: selectedGroups.map(\.id),
note: note.isEmpty ? nil : note,
withHighlights: withHighlights)
} catch {
showError = true
}
@ -111,6 +117,13 @@ struct RecommendToView: View {
.padding(.top, 24)
.padding(.leading, 16)
)
if viewModel.highlightCount > 0 {
Toggle(isOn: $viewModel.withHighlights, label: {
HStack(alignment: .firstTextBaseline) {
Text("Include \(viewModel.highlightCount) highlight\(viewModel.highlightCount > 1 ? "s" : "")")
}
})
}
Spacer()
}
.padding(16)

View File

@ -362,7 +362,7 @@ struct WebReaderContainerView: View {
NavigationView {
RecommendToView(
dataService: dataService,
viewModel: RecommendToViewModel(pageID: item.unwrappedID)
viewModel: RecommendToViewModel(pageID: item.unwrappedID, highlightCount: item.highlights?.count ?? 0)
)
}.onDisappear {
showRecommendSheet = false

View File

@ -9677,6 +9677,7 @@ extension Objects {
let moveLabel: [String: Unions.MoveLabelResult]
let optInFeature: [String: Unions.OptInFeatureResult]
let recommend: [String: Unions.RecommendResult]
let recommendHighlights: [String: Unions.RecommendHighlightsResult]
let reportItem: [String: Objects.ReportItemResult]
let revokeApiKey: [String: Unions.RevokeApiKeyResult]
let saveArticleReadingProgress: [String: Unions.SaveArticleReadingProgressResult]
@ -9851,6 +9852,10 @@ extension Objects.Mutation: Decodable {
if let value = try container.decode(Unions.RecommendResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "recommendHighlights":
if let value = try container.decode(Unions.RecommendHighlightsResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "reportItem":
if let value = try container.decode(Objects.ReportItemResult?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
@ -10016,6 +10021,7 @@ extension Objects.Mutation: Decodable {
moveLabel = map["moveLabel"]
optInFeature = map["optInFeature"]
recommend = map["recommend"]
recommendHighlights = map["recommendHighlights"]
reportItem = map["reportItem"]
revokeApiKey = map["revokeApiKey"]
saveArticleReadingProgress = map["saveArticleReadingProgress"]
@ -10640,6 +10646,25 @@ extension Fields where TypeLock == Objects.Mutation {
}
}
func recommendHighlights<Type>(input: InputObjects.RecommendHighlightsInput, selection: Selection<Type, Unions.RecommendHighlightsResult>) throws -> Type {
let field = GraphQLField.composite(
name: "recommendHighlights",
arguments: [Argument(name: "input", type: "RecommendHighlightsInput!", value: input)],
selection: selection.selection
)
select(field)
switch response {
case let .decoding(data):
if let data = data.recommendHighlights[field.alias!] {
return try selection.decode(data: data)
}
throw HttpError.badpayload
case .mocking:
return selection.mock()
}
}
func reportItem<Type>(input: InputObjects.ReportItemInput, selection: Selection<Type, Objects.ReportItemResult>) throws -> Type {
let field = GraphQLField.composite(
name: "reportItem",
@ -13663,10 +13688,140 @@ extension Selection where TypeLock == Never, Type == Never {
typealias RecommendError<T> = Selection<T, Objects.RecommendError>
}
extension Objects {
struct RecommendHighlightsError {
let __typename: TypeName = .recommendHighlightsError
let errorCodes: [String: [Enums.RecommendHighlightsErrorCode]]
enum TypeName: String, Codable {
case recommendHighlightsError = "RecommendHighlightsError"
}
}
}
extension Objects.RecommendHighlightsError: 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.RecommendHighlightsErrorCode]?.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.RecommendHighlightsError {
func errorCodes() throws -> [Enums.RecommendHighlightsErrorCode] {
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 RecommendHighlightsError<T> = Selection<T, Objects.RecommendHighlightsError>
}
extension Objects {
struct RecommendHighlightsSuccess {
let __typename: TypeName = .recommendHighlightsSuccess
let success: [String: Bool]
enum TypeName: String, Codable {
case recommendHighlightsSuccess = "RecommendHighlightsSuccess"
}
}
}
extension Objects.RecommendHighlightsSuccess: 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 "success":
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)."
)
)
}
}
success = map["success"]
}
}
extension Fields where TypeLock == Objects.RecommendHighlightsSuccess {
func success() throws -> Bool {
let field = GraphQLField.leaf(
name: "success",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
if let data = data.success[field.alias!] {
return data
}
throw HttpError.badpayload
case .mocking:
return Bool.mockValue
}
}
}
extension Selection where TypeLock == Never, Type == Never {
typealias RecommendHighlightsSuccess<T> = Selection<T, Objects.RecommendHighlightsSuccess>
}
extension Objects {
struct RecommendSuccess {
let __typename: TypeName = .recommendSuccess
let taskNames: [String: [String]]
let success: [String: Bool]
enum TypeName: String, Codable {
case recommendSuccess = "RecommendSuccess"
@ -13686,8 +13841,8 @@ extension Objects.RecommendSuccess: Decodable {
let field = GraphQLField.getFieldNameFromAlias(alias)
switch field {
case "taskNames":
if let value = try container.decode([String]?.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:
@ -13700,26 +13855,26 @@ extension Objects.RecommendSuccess: Decodable {
}
}
taskNames = map["taskNames"]
success = map["success"]
}
}
extension Fields where TypeLock == Objects.RecommendSuccess {
func taskNames() throws -> [String] {
func success() throws -> Bool {
let field = GraphQLField.leaf(
name: "taskNames",
name: "success",
arguments: []
)
select(field)
switch response {
case let .decoding(data):
if let data = data.taskNames[field.alias!] {
if let data = data.success[field.alias!] {
return data
}
throw HttpError.badpayload
case .mocking:
return []
return Bool.mockValue
}
}
}
@ -25762,11 +25917,85 @@ extension Selection where TypeLock == Never, Type == Never {
typealias RecentSearchesResult<T> = Selection<T, Unions.RecentSearchesResult>
}
extension Unions {
struct RecommendHighlightsResult {
let __typename: TypeName
let errorCodes: [String: [Enums.RecommendHighlightsErrorCode]]
let success: [String: Bool]
enum TypeName: String, Codable {
case recommendHighlightsError = "RecommendHighlightsError"
case recommendHighlightsSuccess = "RecommendHighlightsSuccess"
}
}
}
extension Unions.RecommendHighlightsResult: 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.RecommendHighlightsErrorCode]?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "success":
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")!)
errorCodes = map["errorCodes"]
success = map["success"]
}
}
extension Fields where TypeLock == Unions.RecommendHighlightsResult {
func on<Type>(recommendHighlightsError: Selection<Type, Objects.RecommendHighlightsError>, recommendHighlightsSuccess: Selection<Type, Objects.RecommendHighlightsSuccess>) throws -> Type {
select([GraphQLField.fragment(type: "RecommendHighlightsError", selection: recommendHighlightsError.selection), GraphQLField.fragment(type: "RecommendHighlightsSuccess", selection: recommendHighlightsSuccess.selection)])
switch response {
case let .decoding(data):
switch data.__typename {
case .recommendHighlightsError:
let data = Objects.RecommendHighlightsError(errorCodes: data.errorCodes)
return try recommendHighlightsError.decode(data: data)
case .recommendHighlightsSuccess:
let data = Objects.RecommendHighlightsSuccess(success: data.success)
return try recommendHighlightsSuccess.decode(data: data)
}
case .mocking:
return recommendHighlightsError.mock()
}
}
}
extension Selection where TypeLock == Never, Type == Never {
typealias RecommendHighlightsResult<T> = Selection<T, Unions.RecommendHighlightsResult>
}
extension Unions {
struct RecommendResult {
let __typename: TypeName
let errorCodes: [String: [Enums.RecommendErrorCode]]
let taskNames: [String: [String]]
let success: [String: Bool]
enum TypeName: String, Codable {
case recommendError = "RecommendError"
@ -25791,8 +26020,8 @@ extension Unions.RecommendResult: Decodable {
if let value = try container.decode([Enums.RecommendErrorCode]?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
case "taskNames":
if let value = try container.decode([String]?.self, forKey: codingKey) {
case "success":
if let value = try container.decode(Bool?.self, forKey: codingKey) {
map.set(key: field, hash: alias, value: value as Any)
}
default:
@ -25808,7 +26037,7 @@ extension Unions.RecommendResult: Decodable {
__typename = try container.decode(TypeName.self, forKey: DynamicCodingKeys(stringValue: "__typename")!)
errorCodes = map["errorCodes"]
taskNames = map["taskNames"]
success = map["success"]
}
}
@ -25823,7 +26052,7 @@ extension Fields where TypeLock == Unions.RecommendResult {
let data = Objects.RecommendError(errorCodes: data.errorCodes)
return try recommendError.decode(data: data)
case .recommendSuccess:
let data = Objects.RecommendSuccess(taskNames: data.taskNames)
let data = Objects.RecommendSuccess(success: data.success)
return try recommendSuccess.decode(data: data)
}
case .mocking:
@ -29262,6 +29491,17 @@ extension Enums {
}
}
extension Enums {
/// RecommendHighlightsErrorCode
enum RecommendHighlightsErrorCode: String, CaseIterable, Codable {
case badRequest = "BAD_REQUEST"
case notFound = "NOT_FOUND"
case unauthorized = "UNAUTHORIZED"
}
}
extension Enums {
/// ReminderErrorCode
enum ReminderErrorCode: String, CaseIterable, Codable {
@ -30302,9 +30542,11 @@ extension InputObjects {
}
extension InputObjects {
struct RecommendInput: Encodable, Hashable {
struct RecommendHighlightsInput: Encodable, Hashable {
var groupIds: [String]
var highlightIds: [String]
var note: OptionalArgument<String> = .absent()
var pageId: String
@ -30312,18 +30554,47 @@ extension InputObjects {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(groupIds, forKey: .groupIds)
try container.encode(highlightIds, forKey: .highlightIds)
if note.hasValue { try container.encode(note, forKey: .note) }
try container.encode(pageId, forKey: .pageId)
}
enum CodingKeys: String, CodingKey {
case groupIds
case highlightIds
case note
case pageId
}
}
}
extension InputObjects {
struct RecommendInput: Encodable, Hashable {
var groupIds: [String]
var note: OptionalArgument<String> = .absent()
var pageId: String
var recommendedWithHighlights: OptionalArgument<Bool> = .absent()
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(groupIds, forKey: .groupIds)
if note.hasValue { try container.encode(note, forKey: .note) }
try container.encode(pageId, forKey: .pageId)
if recommendedWithHighlights.hasValue { try container.encode(recommendedWithHighlights, forKey: .recommendedWithHighlights) }
}
enum CodingKeys: String, CodingKey {
case groupIds
case note
case pageId
case recommendedWithHighlights
}
}
}
extension InputObjects {
struct ReportItemInput: Encodable, Hashable {
var itemUrl: String

View File

@ -4,9 +4,9 @@ import Models
import SwiftGraphQL
public extension DataService {
func recommendPage(pageID: String, groupIDs: [String], note: String?) async throws {
func recommendPage(pageID: String, groupIDs: [String], note: String?, withHighlights: Bool?) async throws {
enum MutationResult {
case saved(taskNames: [String])
case saved(success: Bool)
case error(errorMessage: String)
}
@ -14,14 +14,14 @@ public extension DataService {
try $0.on(
recommendError: .init { .error(errorMessage: try $0.errorCodes().first.toString()) },
recommendSuccess: .init {
.saved(taskNames: try $0.taskNames())
.saved(success: try $0.success())
}
)
}
let mutation = Selection.Mutation {
try $0.recommend(
input: .init(groupIds: groupIDs, note: OptionalArgument(note), pageId: pageID),
input: .init(groupIds: groupIDs, note: OptionalArgument(note), pageId: pageID, recommendedWithHighlights: OptionalArgument(withHighlights)),
selection: selection
)
}