mirror of
https://github.com/omnivore-app/omnivore.git
synced 2026-03-11 08:54:26 +00:00
Improve label search in the apply views
This commit is contained in:
parent
8d452094d6
commit
57289cb0c4
6 changed files with 105 additions and 82 deletions
|
|
@ -181,11 +181,24 @@ public struct ShareExtensionView: View {
|
|||
LabelsMasonaryView(labels: labelsViewModel.labels.applySearchFilter(labelsViewModel.labelSearchFilter),
|
||||
selectedLabels: labelsViewModel.selectedLabels.applySearchFilter(labelsViewModel.labelSearchFilter),
|
||||
onLabelTap: onLabelTap)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.bottom, 16)
|
||||
.background(Color.appButtonBackground)
|
||||
.cornerRadius(8)
|
||||
Button(
|
||||
action: { labelsViewModel.showCreateLabelModal = true },
|
||||
label: {
|
||||
HStack {
|
||||
Image(systemName: "tag").foregroundColor(.blue)
|
||||
Text(
|
||||
labelsViewModel.labelSearchFilter.count > 0 ?
|
||||
"Create: \"\(labelsViewModel.labelSearchFilter)\" label" :
|
||||
LocalText.createLabelMessage
|
||||
).foregroundColor(.blue)
|
||||
.font(Font.system(size: 14))
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
)
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
.padding(10)
|
||||
}.background(Color.appButtonBackground)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -462,7 +475,7 @@ public struct ShareExtensionView: View {
|
|||
viewModel.savePage(extensionContext: extensionContext)
|
||||
}
|
||||
.sheet(isPresented: $labelsViewModel.showCreateLabelModal) {
|
||||
CreateLabelView(viewModel: labelsViewModel)
|
||||
CreateLabelView(viewModel: labelsViewModel, newLabelName: labelsViewModel.labelSearchFilter)
|
||||
}
|
||||
.alert("Before saving an article select text in Safari to create a highlight on save.",
|
||||
isPresented: $showHighlightInstructionAlert) {
|
||||
|
|
@ -470,15 +483,6 @@ public struct ShareExtensionView: View {
|
|||
}
|
||||
.task {
|
||||
await labelsViewModel.loadLabelsFromStore(dataService: viewModel.services.dataService)
|
||||
}
|
||||
.sheet(isPresented: $showSearchLabels) {
|
||||
ApplyLabelsView(mode: .list(self.labelsViewModel.selectedLabels), isSearchFocused: true) { labels in
|
||||
self.labelsViewModel.selectedLabels = labels
|
||||
if let itemID = self.viewModel.linkedItem?.unwrappedID {
|
||||
self.labelsViewModel.saveItemLabelChanges(itemID: itemID, dataService: self.viewModel.services.dataService)
|
||||
}
|
||||
}
|
||||
}
|
||||
.environmentObject(viewModel.services.dataService)
|
||||
}.environmentObject(viewModel.services.dataService)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,75 +48,87 @@ struct ApplyLabelsView: View {
|
|||
}
|
||||
|
||||
var innerBody: some View {
|
||||
List {
|
||||
Section(header: Spacer(minLength: 0)) {
|
||||
SearchBar(searchTerm: $viewModel.labelSearchFilter)
|
||||
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||
.listRowBackground(Color.clear)
|
||||
}
|
||||
Section {
|
||||
Button(
|
||||
action: { viewModel.showCreateLabelModal = true },
|
||||
label: {
|
||||
HStack {
|
||||
Image(systemName: "plus.circle.fill").foregroundColor(.green)
|
||||
Text(LocalText.createLabelMessage).foregroundColor(.appGrayTextContrast)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
)
|
||||
.disabled(viewModel.isLoading)
|
||||
}
|
||||
Section {
|
||||
ForEach(viewModel.labels.applySearchFilter(viewModel.labelSearchFilter), id: \.self) { label in
|
||||
Button(
|
||||
action: {
|
||||
if isSelected(label) {
|
||||
viewModel.selectedLabels.removeAll(where: { $0.id == label.id })
|
||||
} else {
|
||||
viewModel.selectedLabels.append(label)
|
||||
}
|
||||
},
|
||||
label: {
|
||||
HStack {
|
||||
TextChip(feedItemLabel: label)
|
||||
Spacer()
|
||||
VStack {
|
||||
SearchBar(searchTerm: $viewModel.labelSearchFilter)
|
||||
.padding(.vertical, 8)
|
||||
.padding(.horizontal, 16)
|
||||
|
||||
List {
|
||||
Section {
|
||||
ForEach(viewModel.labels.applySearchFilter(viewModel.labelSearchFilter), id: \.self) { label in
|
||||
Button(
|
||||
action: {
|
||||
if isSelected(label) {
|
||||
Image(systemName: "checkmark")
|
||||
viewModel.selectedLabels.removeAll(where: { $0.id == label.id })
|
||||
} else {
|
||||
viewModel.selectedLabels.append(label)
|
||||
}
|
||||
},
|
||||
label: {
|
||||
HStack {
|
||||
TextChip(feedItemLabel: label)
|
||||
Spacer()
|
||||
if isSelected(label) {
|
||||
Image(systemName: "checkmark")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
.listRowInsets(EdgeInsets(top: 0, leading: 8, bottom: 0, trailing: 8))
|
||||
#if os(macOS)
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
#endif
|
||||
)
|
||||
.padding(.vertical, 5)
|
||||
#if os(macOS)
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
#endif
|
||||
}
|
||||
createLabelButton
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
.listStyle(PlainListStyle())
|
||||
.navigationTitle(mode.navTitle)
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
cancelButton
|
||||
}
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
saveItemChangesButton
|
||||
}
|
||||
}
|
||||
#else
|
||||
.toolbar {
|
||||
ToolbarItemGroup {
|
||||
cancelButton
|
||||
saveItemChangesButton
|
||||
}
|
||||
}
|
||||
#endif
|
||||
.sheet(isPresented: $viewModel.showCreateLabelModal) {
|
||||
CreateLabelView(viewModel: viewModel, newLabelName: viewModel.labelSearchFilter)
|
||||
}
|
||||
}
|
||||
.padding(.top, 0)
|
||||
.navigationTitle(mode.navTitle)
|
||||
#if os(iOS)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
cancelButton
|
||||
}
|
||||
ToolbarItem(placement: .navigationBarTrailing) {
|
||||
saveItemChangesButton
|
||||
}
|
||||
|
||||
var createLabelButton: some View {
|
||||
Button(
|
||||
action: { viewModel.showCreateLabelModal = true },
|
||||
label: {
|
||||
HStack {
|
||||
Image(systemName: "tag").foregroundColor(.blue)
|
||||
Text(
|
||||
viewModel.labelSearchFilter.count > 0 ?
|
||||
"Create: \"\(viewModel.labelSearchFilter)\" label" :
|
||||
LocalText.createLabelMessage
|
||||
).foregroundColor(.blue)
|
||||
.font(Font.system(size: 14))
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
#else
|
||||
.toolbar {
|
||||
ToolbarItemGroup {
|
||||
cancelButton
|
||||
saveItemChangesButton
|
||||
}
|
||||
}
|
||||
#endif
|
||||
.sheet(isPresented: $viewModel.showCreateLabelModal) {
|
||||
CreateLabelView(viewModel: viewModel)
|
||||
}
|
||||
)
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
.disabled(viewModel.isLoading)
|
||||
.listRowSeparator(.hidden, edges: .bottom)
|
||||
.padding(.vertical, 10)
|
||||
}
|
||||
|
||||
var saveItemChangesButton: some View {
|
||||
|
|
@ -151,7 +163,6 @@ struct ApplyLabelsView: View {
|
|||
EmptyView()
|
||||
} else {
|
||||
innerBody
|
||||
.padding(.top, -20) // This is a hack to give us a bit more room on the page
|
||||
}
|
||||
}
|
||||
#elseif os(macOS)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ struct LabelsView: View {
|
|||
Button(LocalText.cancelGeneric, role: .cancel) { self.labelToRemove = nil }
|
||||
}
|
||||
.sheet(isPresented: $viewModel.showCreateLabelModal) {
|
||||
CreateLabelView(viewModel: viewModel)
|
||||
CreateLabelView(viewModel: viewModel, newLabelName: viewModel.labelSearchFilter)
|
||||
}
|
||||
.task { await viewModel.loadLabels(dataService: dataService, item: nil) }
|
||||
}
|
||||
|
|
@ -85,9 +85,14 @@ struct CreateLabelView: View {
|
|||
@EnvironmentObject var dataService: DataService
|
||||
@ObservedObject var viewModel: LabelsViewModel
|
||||
|
||||
@State private var newLabelName = ""
|
||||
@State private var newLabelName: String
|
||||
@State private var newLabelColor = Color.clear
|
||||
|
||||
init(viewModel: LabelsViewModel, newLabelName: String = "") {
|
||||
self.viewModel = viewModel
|
||||
self.newLabelName = newLabelName
|
||||
}
|
||||
|
||||
var shouldDisableCreateButton: Bool {
|
||||
viewModel.isLoading || newLabelName.isEmpty || newLabelColor == .clear
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ import Views
|
|||
|
||||
if let label = dataService.viewContext.object(with: labelObjectID) as? LinkedItemLabel {
|
||||
labels.insert(label, at: 0)
|
||||
unselectedLabels.insert(label, at: 0)
|
||||
selectedLabels.insert(label, at: 0)
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
|
|
|
|||
|
|
@ -52,5 +52,8 @@ public struct SearchBar: View {
|
|||
searchTerm = ""
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
isFocused = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ Readability.prototype = {
|
|||
// Readability-readerable.js. Please keep both copies in sync.
|
||||
articleNegativeLookBehindCandidates: /breadcrumbs|breadcrumb|utils|trilist/i,
|
||||
articleNegativeLookAheadCandidates: /outstream(.?)_|sub(.?)_|m_|omeda-promo-|in-article-advert|block-ad-.*/i,
|
||||
unlikelyCandidates: /\bad\b|ai2html|banner|breadcrumbs|breadcrumb|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager(?!ow)|popup|yom-remote|copyright|keywords|outline|infinite-list|beta|recirculation|site-index|hide-for-print|post-end-share-cta|post-end-cta-full|post-footer|post-head|post-tag|li-date|main-navigation|programtic-ads|outstream_article|hfeed|comment-holder|back-to-top|show-up-next|onward-journey|topic-tracker|list-nav|block-ad-entity|adSpecs|gift-article-button|modal-title|in-story-masthead|share-tools|standard-dock|expanded-dock|margins-h|subscribe-dialog|icon|bumped|dvz-social-media-buttons/i,
|
||||
unlikelyCandidates: /\bad\b|ai2html|banner|breadcrumbs|breadcrumb|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager(?!ow)|popup|yom-remote|copyright|keywords|outline|infinite-list|beta|recirculation|site-index|hide-for-print|post-end-share-cta|post-end-cta-full|post-footer|post-head|post-tag|li-date|main-navigation|programtic-ads|outstream_article|hfeed|comment-holder|back-to-top|show-up-next|onward-journey|topic-tracker|list-nav|block-ad-entity|adSpecs|gift-article-button|modal-title|in-story-masthead|share-tools|standard-dock|expanded-dock|margins-h|subscribe-dialog|icon|bumped|dvz-social-media-buttons|post-toc|mobile-menu|mobile-navbar/i,
|
||||
// okMaybeItsACandidate: /and|article(?!-breadcrumb)|body|column|content|main|shadow|post-header/i,
|
||||
get okMaybeItsACandidate() {
|
||||
return new RegExp(`and|(?<!${this.articleNegativeLookAheadCandidates.source})article(?!-(${this.articleNegativeLookBehindCandidates.source}))|body|column|content|^(?!main-navigation|main-header)main|shadow|post-header|hfeed site|blog-posts hfeed|container-banners|menu-opacity|header-with-anchor-widget`, 'i')
|
||||
|
|
|
|||
Loading…
Reference in a new issue