Improve subscription labels rules

This commit is contained in:
Jackson Harper
2023-12-20 14:20:40 +08:00
parent afe926e45d
commit d4628edcaf
2 changed files with 70 additions and 25 deletions

View File

@ -24,8 +24,8 @@ typealias OperationStatusHandler = (_: OperationStatus) -> Void
@Published var isLoading = true
@Published var feeds = [Subscription]()
@Published var newsletters = [Subscription]()
@Published var rules = [Rule]()
@Published var labels = [LinkedItemLabel]()
@Published var rules: [Rule]?
@Published var labels: [LinkedItemLabel]?
@Published var hasNetworkError = false
@Published var subscriptionNameToCancel: String?
@ -53,13 +53,19 @@ typealias OperationStatusHandler = (_: OperationStatus) -> Void
rules = try await dataService.rules()
} catch {
print("error fetching rules and labels", error)
rules = []
}
await loadLabelsFromStore(dataService: dataService)
await loadLabels(dataService: dataService)
isLoading = false
}
func loadLabels(dataService: DataService) async {
_ = try? await dataService.labels()
await loadLabelsFromStore(dataService: dataService)
}
func loadLabelsFromStore(dataService: DataService) async {
let fetchRequest: NSFetchRequest<Models.LinkedItemLabel> = LinkedItemLabel.fetchRequest()
@ -112,12 +118,30 @@ typealias OperationStatusHandler = (_: OperationStatus) -> Void
}
}
func setLabelsRule(dataService: DataService, ruleName: String, filter: String, labelIDs: [String]) async {
async {
func setLabelsRule(dataService: DataService, existingRule: Rule?, ruleName: String, filter: String, labelIDs: [String]) async {
Task {
operationMessage = "Creating label rule..."
operationStatus = .isPerforming
do {
try await dataService.createAddLabelsRule(name: ruleName, filter: filter, labelIDs: labelIDs)
// Make sure the labels have been created
await loadLabels(dataService: dataService)
let existingLabelIDs = labels?.map(\.unwrappedID) ?? []
if labelIDs.first(where: { !existingLabelIDs.contains($0) }) != nil {
throw BasicError.message(messageText: "Label not created")
}
_ = try await dataService.createOrUpdateAddLabelsRule(
existingID: existingRule?.id,
name: ruleName,
filter: filter,
labelIDs: labelIDs
)
if let newRules = try? await dataService.rules() {
if !newRules.contains(where: { $0.name == ruleName }) {
throw BasicError.message(messageText: "Rule not created")
}
rules = newRules
}
operationMessage = "Rule created"
operationStatus = .success
} catch {
@ -398,10 +422,16 @@ struct SubscriptionSettingsView: View {
@State var folderSelection: String = ""
@State var showLabelsSelector = false
@State var isLoadingRule = false
let unsubscribe: (_: Subscription) -> Void
@Environment(\.dismiss) private var dismiss
var existingRule: Rule? {
viewModel.rules?.first { $0.name == ruleName }
}
var ruleName: String {
if let url = subscription.url, subscription.type == .newsletter {
return "system.autoLabel.(\(url))"
@ -416,6 +446,15 @@ struct SubscriptionSettingsView: View {
return "subscription:\"\(subscription.name)\""
}
var ruleLabels: [LinkedItemLabel]? {
if let labelIDs = existingRule?.actions.flatMap(\.params) {
return Array(labelIDs.compactMap { labelID in
viewModel.labels?.first(where: { $0.unwrappedID == labelID })
})
}
return nil
}
var folderRow: some View {
HStack {
Picker("Destination Folder", selection: $folderSelection) {
@ -435,10 +474,11 @@ struct SubscriptionSettingsView: View {
.onChange(of: prefetchContent) { newValue in
Task {
viewModel.showOperationToast = true
await viewModel.updateSubscription(dataService: dataService, subscription: subscription, fetchContent: newValue)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1500)) {
viewModel.showOperationToast = false
}
await viewModel.updateSubscription(
dataService: dataService,
subscription: subscription,
fetchContent: newValue
)
}
}
}
@ -448,18 +488,18 @@ struct SubscriptionSettingsView: View {
HStack {
Text("Add Labels")
Spacer()
Button(action: { showLabelsSelector = true }, label: {
if let rule = viewModel.rules.first(where: { $0.name == ruleName }) {
let labelIDs = rule.actions.flatMap(\.params)
let labelNames = Array(labelIDs.compactMap { labelID in
viewModel.labels.first(where: { $0.unwrappedID == labelID })?.unwrappedName
})
Text("[\(labelNames.joined(separator: ","))]")
} else {
Text("[none]")
}
})
if isLoadingRule || viewModel.rules != nil {
Button(action: { showLabelsSelector = true }, label: {
if let ruleLabels = ruleLabels {
let labelNames = ruleLabels.map(\.unwrappedName)
Text("[\(labelNames.joined(separator: ","))]")
} else {
Text("[none]")
}
})
} else {
ProgressView()
}
}
}
@ -513,17 +553,20 @@ struct SubscriptionSettingsView: View {
}
}
.sheet(isPresented: $showLabelsSelector) {
ApplyLabelsView(mode: .list([]), onSave: { labels in
ApplyLabelsView(mode: .list(ruleLabels ?? []), onSave: { labels in
Task {
isLoadingRule = true
viewModel.showOperationToast = true
await viewModel.setLabelsRule(
dataService: dataService,
existingRule: existingRule,
ruleName: ruleName,
filter: ruleFilter,
labelIDs: labels.map(\.unwrappedID)
)
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(1500)) {
viewModel.showOperationToast = false
isLoadingRule = true
}
}
})

View File

@ -43,7 +43,7 @@ let ruleSelection = Selection.Rule {
}
public extension DataService {
func createAddLabelsRule(name: String, filter: String, labelIDs: [String]) async throws -> Rule {
func createOrUpdateAddLabelsRule(existingID: String?, name: String, filter: String, labelIDs: [String]) async throws -> Rule {
enum MutationResult {
case result(rule: Rule)
case error(errorMessage: String)
@ -62,7 +62,9 @@ public extension DataService {
actions: [InputObjects.RuleActionInput(params: labelIDs, type: .addLabel)],
enabled: true,
eventTypes: [.pageCreated],
filter: filter, name: name
filter: filter,
id: OptionalArgument(existingID),
name: name
),
selection: selection
)