summaryrefslogtreecommitdiff
path: root/DomainDig/DomainDigUI.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-07-17 10:45:42 -0500
committerChristian Cleberg <[email protected]>2026-07-17 10:57:30 -0500
commitfbf2d9bf2cf50eb681afe18deac06a96c04004e6 (patch)
treef337f6826c283d4246cdde824786bd18b6c770b3 /DomainDig/DomainDigUI.swift
parent6e273c2676ce29cef057d117e4427e031886e743 (diff)
downloaddomain-dig-fbf2d9bf2cf50eb681afe18deac06a96c04004e6.tar.gz
domain-dig-fbf2d9bf2cf50eb681afe18deac06a96c04004e6.tar.bz2
domain-dig-fbf2d9bf2cf50eb681afe18deac06a96c04004e6.zip
v4.7.0: Add watchlist tags and saved filter views
- TrackedDomain.tags: [String] (backward-compatible custom decode), with updateTags(_:for:) and a normalized/deduplicated write path. - Tag editing in TrackedDomainDetailView (comma-separated field, chip display). - Tag filter chips in WatchlistView (TagFilterChipRowView), integrated into filteredTrackedDomains alongside the existing filter/search. - Saved views: name + snapshot the current tag/filter/sort as a WatchlistSavedView preset (UserDefaults-backed, not part of backup/restore), with a management sheet to apply or delete presets.
Diffstat (limited to 'DomainDig/DomainDigUI.swift')
-rw-r--r--DomainDig/DomainDigUI.swift54
1 files changed, 54 insertions, 0 deletions
diff --git a/DomainDig/DomainDigUI.swift b/DomainDig/DomainDigUI.swift
index 592d7a7..272c678 100644
--- a/DomainDig/DomainDigUI.swift
+++ b/DomainDig/DomainDigUI.swift
@@ -332,3 +332,57 @@ struct CollapsibleSectionView<HeaderTrailing: View, Content: View>: View {
}
}
}
+
+/// A horizontally scrolling row of read-only tag chips, e.g. for a tracked
+/// domain's detail view.
+struct TagChipRowView: View {
+ let tags: [String]
+
+ var body: some View {
+ ScrollView(.horizontal, showsIndicators: false) {
+ HStack(spacing: 8) {
+ ForEach(tags, id: \.self) { tag in
+ Text(tag)
+ .font(.caption)
+ .padding(.horizontal, 10)
+ .padding(.vertical, 5)
+ .background(Color(.systemGray5).opacity(0.6), in: Capsule())
+ }
+ }
+ }
+ }
+}
+
+/// A horizontally scrolling row of selectable tag chips used to filter a list,
+/// with an "All" chip to clear the selection.
+struct TagFilterChipRowView: View {
+ let tags: [String]
+ @Binding var selection: String?
+
+ var body: some View {
+ ScrollView(.horizontal, showsIndicators: false) {
+ HStack(spacing: 8) {
+ filterChip(title: "All", isSelected: selection == nil) {
+ selection = nil
+ }
+ ForEach(tags, id: \.self) { tag in
+ filterChip(title: tag, isSelected: selection == tag) {
+ selection = (selection == tag) ? nil : tag
+ }
+ }
+ }
+ }
+ }
+
+ private func filterChip(title: String, isSelected: Bool, action: @escaping () -> Void) -> some View {
+ Button(action: action) {
+ Text(title)
+ .font(.caption)
+ .padding(.horizontal, 10)
+ .padding(.vertical, 5)
+ .background(isSelected ? Color.cyan.opacity(0.3) : Color(.systemGray5).opacity(0.6), in: Capsule())
+ .foregroundStyle(isSelected ? Color.cyan : Color.primary)
+ }
+ .buttonStyle(.plain)
+ }
+}