summaryrefslogtreecommitdiff
path: root/DomainDig/ContentView.swift
diff options
context:
space:
mode:
Diffstat (limited to 'DomainDig/ContentView.swift')
-rw-r--r--DomainDig/ContentView.swift49
1 files changed, 45 insertions, 4 deletions
diff --git a/DomainDig/ContentView.swift b/DomainDig/ContentView.swift
index 0386211..76817cd 100644
--- a/DomainDig/ContentView.swift
+++ b/DomainDig/ContentView.swift
@@ -37,6 +37,7 @@ struct ContentView: View {
@State private var collapsedSections: Set<ResultSection> = [.network]
@State private var showingCurrentDomainWorkflowSheet = false
@State private var showingBatchWorkflowSheet = false
+ @State private var showingTimeline = false
var body: some View {
let _ = purchaseService.currentTier
@@ -83,7 +84,8 @@ struct ContentView: View {
title: "Latest Changes",
sections: viewModel.currentDiffSections,
contextNote: viewModel.currentChangeSummary?.contextNote,
- showsUnchanged: false
+ showsUnchanged: false,
+ highlightedSectionID: nil
)
.padding(.top, appDensity.metrics.sectionSpacing)
}
@@ -230,6 +232,11 @@ struct ContentView: View {
availableDomains: viewModel.batchResults.map(\.domain)
)
}
+ .sheet(isPresented: $showingTimeline) {
+ NavigationStack {
+ TimelineView(viewModel: viewModel, domain: viewModel.searchedDomain)
+ }
+ }
}
private var inputSection: some View {
@@ -439,6 +446,11 @@ struct ContentView: View {
Button("Add to workflow") {
showingCurrentDomainWorkflowSheet = true
}
+ if !viewModel.historyEntries(for: viewModel.searchedDomain).isEmpty {
+ Button("Open timeline") {
+ showingTimeline = true
+ }
+ }
if FeatureAccessService.hasAccess(to: .advancedExports) {
Button("Copy report JSON") {
guard let json = viewModel.exportJSONString() else { return }
@@ -1048,8 +1060,9 @@ struct DomainDiffView: View {
let sections: [DomainDiffSection]
let contextNote: String?
let showsUnchanged: Bool
+ let highlightedSectionID: String?
- @State private var collapsedSections = Set<UUID>()
+ @State private var collapsedSections = Set<String>()
@State private var showsLowSeverity = false
private var filteredSections: [DomainDiffSection] {
@@ -1064,7 +1077,7 @@ struct DomainDiffView: View {
}
return item.severity >= .medium || (showsUnchanged && item.changeType == .unchanged)
}
- return DomainDiffSection(title: section.title, items: items)
+ return DomainDiffSection(id: section.id, title: section.title, items: items)
}
.filter { !$0.items.isEmpty }
}
@@ -1104,7 +1117,7 @@ struct DomainDiffView: View {
.font(.system(.caption, design: .monospaced))
.foregroundStyle(.secondary)
Spacer()
- Text("\(item.severity.title) • \(changeLabel(for: item.changeType))")
+ Text("\(item.changeType.marker) \(item.severity.title) • \(changeLabel(for: item.changeType))")
.font(.system(.caption2, design: .monospaced))
.foregroundStyle(changeColor(for: item))
.padding(.horizontal, 8)
@@ -1154,9 +1167,19 @@ struct DomainDiffView: View {
}
}
}
+ .id(section.id)
+ .overlay {
+ if highlightedSectionID == section.id {
+ RoundedRectangle(cornerRadius: 12)
+ .stroke(Color.cyan.opacity(0.55), lineWidth: 1)
+ }
+ }
}
}
}
+ .onAppear {
+ collapsedSections = Set(sections.filter { !showsUnchanged && !$0.hasChanges }.map(\.id))
+ }
}
private func changeLabel(for changeType: DiffChangeType) -> String {
@@ -2460,6 +2483,24 @@ struct SettingsView: View {
}
}
+ Section("History") {
+ Picker(
+ "Auto-prune",
+ selection: Binding(
+ get: { viewModel.historyAutoPruneOption },
+ set: { viewModel.setHistoryAutoPruneOption($0) }
+ )
+ ) {
+ ForEach(HistoryAutoPruneOption.allCases) { option in
+ Text(option.title).tag(option)
+ }
+ }
+
+ Text("History remains local-first. Auto-prune only trims older local snapshots on this device and defaults to unlimited.")
+ .font(appDensity.font(.caption, design: .default))
+ .foregroundStyle(.secondary)
+ }
+
Section("Network") {
Picker("Resolver", selection: $resolverOption) {
ForEach(DNSResolverOption.allCases) { option in