Replace the Tags tab with a tag picker sheet
The tab bar drops from five to four; Tags now opens as a sheet from the + in the library's filter strip, which is the control that was already about adding a tag. Picking a tag pins it as a filter tab rather than pushing to a separate per-tag list. That made TagBookmarksView redundant — the filter tab shows the same thing, in whichever layout you're already using — so it's gone. This also fixes what the + could reach. The old inline menu listed tags found on the loaded page, so it offered 21 of 96 tags, and once a tag filter was active it collapsed to just the tags co-occurring with that one — pinning a second unrelated tag was impossible. The sheet sources names from the tags endpoint via a new BookmarksViewModel.loadAllTags(), and counts still come from loaded bookmarks, so a tag we haven't paged in shows no number rather than a wrong one. The sheet is searchable, marks already-pinned tags with a check, and picking a pinned tag selects that tab instead of duplicating it. Verified by driving the UI: the tab bar is now Bookmarks/Sources/ Podcasts/Search, + opens the sheet with 42 rows where the old menu had 21, and picking "ai" pinned an "ai" tab. Suite passes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JgLHztZGaEHvS3KNeGQmRM
This commit is contained in:
co-authored by
Claude Opus 5
parent
69c2bc7514
commit
8a777ffc83
@@ -65,6 +65,7 @@ struct BookmarksView: View {
|
||||
LibraryFilter(name: "Everything", tag: nil)
|
||||
]
|
||||
@State private var librarySelection: LibraryFilter.ID?
|
||||
@State private var showTags = false
|
||||
|
||||
private var layout: LibraryLayout { LibraryLayout(rawValue: layoutRaw) ?? .list }
|
||||
private var otherLayout: LibraryLayout { layout == .cards ? .list : .cards }
|
||||
@@ -78,8 +79,8 @@ struct BookmarksView: View {
|
||||
LibraryTagStrip(
|
||||
filters: $libraryFilters,
|
||||
selection: $librarySelection,
|
||||
available: availableTags,
|
||||
onChange: applyTagFilter
|
||||
onChange: applyTagFilter,
|
||||
onBrowseTags: { showTags = true }
|
||||
)
|
||||
|
||||
if layout == .cards {
|
||||
@@ -192,6 +193,13 @@ struct BookmarksView: View {
|
||||
.sheet(isPresented: $showAsk) {
|
||||
AskView()
|
||||
}
|
||||
.sheet(isPresented: $showTags) {
|
||||
TagsView(
|
||||
viewModel: viewModel,
|
||||
pinned: Set(libraryFilters.compactMap(\.tag)),
|
||||
onPick: pinTag
|
||||
)
|
||||
}
|
||||
.sheet(isPresented: $showAddBookmark) {
|
||||
AddBookmarkView(viewModel: viewModel)
|
||||
}
|
||||
@@ -319,15 +327,19 @@ struct BookmarksView: View {
|
||||
.animation(.spring(duration: 0.35), value: viewModel.bookmarks.isEmpty)
|
||||
}
|
||||
|
||||
/// Tags of everything currently loaded, heaviest first, minus what's
|
||||
/// already pinned as a tab.
|
||||
private var availableTags: [String] {
|
||||
let taken = Set(libraryFilters.compactMap(\.tag))
|
||||
var counts: [String: Int] = [:]
|
||||
for b in viewModel.bookmarks {
|
||||
for tag in b.tagNames where !taken.contains(tag) { counts[tag, default: 0] += 1 }
|
||||
/// Pin a tag as a filter tab and switch to it. Choosing one that's already
|
||||
/// pinned selects that tab instead of adding a duplicate.
|
||||
private func pinTag(_ tag: String) {
|
||||
if let existing = libraryFilters.first(where: { $0.tag == tag }) {
|
||||
librarySelection = existing.id
|
||||
} else {
|
||||
let new = LibraryFilter(name: tag, tag: tag)
|
||||
withAnimation(.spring(duration: 0.35, bounce: 0.1)) {
|
||||
libraryFilters.append(new)
|
||||
librarySelection = new.id
|
||||
}
|
||||
}
|
||||
return counts.sorted { ($0.value, $1.key) > ($1.value, $0.key) }.map(\.key)
|
||||
applyTagFilter()
|
||||
}
|
||||
|
||||
/// Tag tabs filter server-side through linkding's `#tag` search syntax —
|
||||
|
||||
Reference in New Issue
Block a user