Add feeds, better delete handling

This commit is contained in:
Jackson Harper
2023-11-01 14:29:15 +08:00
parent 3be2db1113
commit 1b85fb0c15
6 changed files with 54 additions and 52 deletions

View File

@ -38,7 +38,7 @@ public struct EditLabelsSheet: View {
if let idx = labelsViewModel.selectedLabels.firstIndex(of: label) {
labelsViewModel.selectedLabels.remove(at: idx)
} else {
labelsViewModel.labelSearchFilter = ""
labelsViewModel.labelSearchFilter = ZWSP
labelsViewModel.selectedLabels.append(label)
}

View File

@ -11,6 +11,8 @@ extension LinkedItemFilter {
return LocalText.readLaterGeneric
case .newsletters:
return LocalText.newslettersGeneric
case .feeds:
return "Feeds"
case .recommended:
return "Recommended"
case .all:

View File

@ -72,7 +72,7 @@ struct ApplyLabelsView: View {
viewModel.selectedLabels.remove(at: idx)
}
} else {
viewModel.labelSearchFilter = ""
viewModel.labelSearchFilter = ZWSP
viewModel.selectedLabels.append(label)
}
},
@ -204,9 +204,11 @@ struct ApplyLabelsView: View {
extension Sequence where Element == LinkedItemLabel {
func applySearchFilter(_ searchFilter: String) -> [LinkedItemLabel] {
if searchFilter.isEmpty {
if searchFilter.isEmpty || searchFilter == ZWSP {
return map { $0 } // return the identity of the sequence
}
return filter { ($0.name ?? "").lowercased().contains(searchFilter.lowercased()) }
let index = searchFilter.index(searchFilter.startIndex, offsetBy: 1)
let trimmed = searchFilter.suffix(from: index).lowercased()
return filter { ($0.name ?? "").lowercased().contains(trimmed) }
}
}

View File

@ -11,7 +11,7 @@ import SwiftUI
@Published var unselectedLabels = Set<LinkedItemLabel>()
@Published var labels = [LinkedItemLabel]()
@Published var showCreateLabelModal = false
@Published var labelSearchFilter = ""
@Published var labelSearchFilter = ZWSP
public init() {}
@ -35,7 +35,9 @@ import SwiftUI
await loadLabelsFromStore(dataService: dataService)
for label in labels {
if selLabels.contains(label) {
selectedLabels.append(label)
if !selectedLabels.contains(label) {
selectedLabels.append(label)
}
} else {
unselectedLabels.insert(label)
}
@ -49,7 +51,9 @@ import SwiftUI
}
for label in self.labels {
if selLabels.contains(label) {
self.selectedLabels.append(label)
if !self.selectedLabels.contains(label) {
self.selectedLabels.append(label)
}
} else {
self.unselectedLabels.insert(label)
}

View File

@ -3,6 +3,8 @@ import Services
import SwiftUI
import Views
let ZWSP = "\u{200B}"
@MainActor
protocol Entry {
func item(parent: LabelsEntryView) -> AnyView
@ -24,14 +26,11 @@ private struct LabelEntry: Entry {
public struct LabelsEntryView: View {
@Binding var searchTerm: String
@State var viewModel: LabelsViewModel
@State var lastSelected = false
@State var justInserted = false
let entries: [Entry]
@State private var totalHeight = CGFloat.zero
@FocusState private var textFieldFocused: Bool
@FocusState private var neverFocused: Bool
public init(
searchTerm: Binding<String>,
@ -44,22 +43,21 @@ public struct LabelsEntryView: View {
}
func onTextSubmit() {
if searchTerm.count < 1 {
let index = searchTerm.index(searchTerm.startIndex, offsetBy: 1)
let trimmed = searchTerm.suffix(from: index).lowercased()
if trimmed.count < 1 {
return
}
// first see if there is a matching label
let term = searchTerm.lowercased()
if let label = viewModel.labels.first(where: { $0.name?.lowercased() == term }) {
justInserted = true
searchTerm = ""
if let label = viewModel.labels.first(where: { $0.name?.lowercased() == trimmed }) {
if !viewModel.selectedLabels.contains(label) {
viewModel.selectedLabels.append(label)
}
searchTerm = ZWSP
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
lastSelected = false
textFieldFocused = true
justInserted = false
}
}
}
@ -78,32 +76,20 @@ public struct LabelsEntryView: View {
.padding(5)
.font(Font.system(size: 14))
.multilineTextAlignment(.leading)
.onChange(of: searchTerm, perform: { newValue in
print("NEW VALUE: ", newValue.count)
.onChange(of: searchTerm, perform: { _ in
if searchTerm.count >= 64 {
searchTerm = String(searchTerm.prefix(64))
}
if searchTerm.isEmpty {
// When we insert a new item we set the text to "" so this block is triggered
// we need to ignore that special case.
if justInserted {
justInserted = false
return
}
if lastSelected {
if viewModel.selectedLabels.count > 0 {
lastSelected = false
viewModel.selectedLabels.removeLast()
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
textFieldFocused = true
}
if viewModel.selectedLabels.count > 0 {
viewModel.selectedLabels.removeLast()
searchTerm = ZWSP
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
textFieldFocused = true
}
} else {
lastSelected = true
searchTerm = "\u{200B}"
searchTerm = ZWSP
}
} else if searchTerm != "\u{200B}" {
lastSelected = false
}
})
.onSubmit {
@ -112,21 +98,21 @@ public struct LabelsEntryView: View {
return result
}
func onTextDelete() -> Bool { if searchTerm.isEmpty {
if lastSelected {
if viewModel.selectedLabels.count > 0 {
viewModel.selectedLabels.removeLast()
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
textFieldFocused = true
}
}
} else {
lastSelected = true
}
return true
}
return false
}
// func onTextDelete() -> Bool { if searchTerm.isEmpty {
// if lastSelected {
// if viewModel.selectedLabels.count > 0 {
// viewModel.selectedLabels.removeLast()
// DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
// textFieldFocused = true
// }
// }
// } else {
// lastSelected = true
// }
// return true
// }
// return false
// }
public var body: some View {
// HStack(spacing: 0) {

View File

@ -2,6 +2,7 @@ import Foundation
public enum LinkedItemFilter: String, CaseIterable {
case inbox
case feeds
case readlater
case newsletters
case recommended
@ -17,6 +18,8 @@ public extension LinkedItemFilter {
switch self {
case .inbox:
return "in:inbox"
case .feeds:
return "label:RSS"
case .readlater:
return "in:library"
case .newsletters:
@ -76,6 +79,11 @@ public extension LinkedItemFilter {
format: "SUBQUERY(labels, $label, $label.name == \"Newsletter\").@count > 0"
)
return NSCompoundPredicate(andPredicateWithSubpredicates: [notInArchivePredicate, newsletterLabelPredicate])
case .feeds:
let feedLabelPredicate = NSPredicate(
format: "SUBQUERY(labels, $label, $label.name == \"RSS\").@count > 0"
)
return NSCompoundPredicate(andPredicateWithSubpredicates: [notInArchivePredicate, feedLabelPredicate])
case .recommended:
// non-archived or deleted items with the Newsletter label
let recommendedPredicate = NSPredicate(