summaryrefslogtreecommitdiff
path: root/DomainDig/DomainCompareView.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-07-17 10:25:53 -0500
committerChristian Cleberg <[email protected]>2026-07-17 10:57:30 -0500
commitd62480233819184db2e55741b05375818ebf3881 (patch)
treebc35d414be25c2ababe4c803f88eaaaba6fa46f7 /DomainDig/DomainCompareView.swift
parent6f79345f8dc078b65d976079332cab3ddf7ec98b (diff)
downloaddomain-dig-d62480233819184db2e55741b05375818ebf3881.tar.gz
domain-dig-d62480233819184db2e55741b05375818ebf3881.tar.bz2
domain-dig-d62480233819184db2e55741b05375818ebf3881.zip
v4.7.0: Add domain-vs-domain comparison
- DiffService.compare(domainA:domainB:) reuses the existing section-diff builders to compare two distinct domains' latest reports, returning a new DomainComparisonResult (parallel to the time-based DomainDiff). - DomainCompareView: pick two tracked domains and render the comparison with the existing DomainDiffView section renderer. - Entry point: "Compare Domains" in the Watchlist toolbar menu, shown once at least two domains are tracked.
Diffstat (limited to 'DomainDig/DomainCompareView.swift')
-rw-r--r--DomainDig/DomainCompareView.swift82
1 files changed, 82 insertions, 0 deletions
diff --git a/DomainDig/DomainCompareView.swift b/DomainDig/DomainCompareView.swift
new file mode 100644
index 0000000..96341c2
--- /dev/null
+++ b/DomainDig/DomainCompareView.swift
@@ -0,0 +1,82 @@
+import SwiftUI
+
+/// Side-by-side comparison of two tracked domains' latest reports, reusing the
+/// same section-diff rendering (`DomainDiffView`) that time-based history diffs
+/// use, via `DiffService.compare(domainA:domainB:)`.
+struct DomainCompareView: View {
+ @Bindable var viewModel: DomainViewModel
+ @State private var domainAID: UUID?
+ @State private var domainBID: UUID?
+
+ private var states: [PortfolioDomainStatus] {
+ viewModel.portfolioDashboardData.domainStates
+ }
+
+ private var stateA: PortfolioDomainStatus? {
+ states.first { $0.trackedDomain.id == domainAID }
+ }
+
+ private var stateB: PortfolioDomainStatus? {
+ states.first { $0.trackedDomain.id == domainBID }
+ }
+
+ private var result: DomainComparisonResult? {
+ guard let stateA, let stateB, stateA.trackedDomain.id != stateB.trackedDomain.id else {
+ return nil
+ }
+ return DiffService.compare(domainA: stateA.report, domainB: stateB.report)
+ }
+
+ var body: some View {
+ List {
+ Section("Domains") {
+ domainPicker("Domain A", selection: $domainAID)
+ domainPicker("Domain B", selection: $domainBID)
+ }
+
+ if domainAID != nil, domainAID == domainBID {
+ Section {
+ Text("Choose two different domains to compare.")
+ .font(.callout)
+ .foregroundStyle(.secondary)
+ }
+ }
+
+ if let result {
+ Section {
+ DomainDiffView(
+ title: "\(result.domainA) vs \(result.domainB)",
+ sections: result.sections,
+ contextNote: result.contextNote,
+ showsUnchanged: true,
+ highlightedSectionID: nil
+ )
+ }
+ .listRowBackground(Color.clear)
+ } else if domainAID == nil || domainBID == nil {
+ Section {
+ EmptyStateCardView(
+ title: "Pick Two Domains",
+ message: "Select a domain in each slot to see a side-by-side comparison across DNS, TLS, ownership, and risk.",
+ suggestion: "Both domains must already be tracked.",
+ systemImage: "arrow.left.arrow.right",
+ showsCardBackground: false
+ )
+ }
+ .listRowBackground(Color(.systemGray6).opacity(0.5))
+ }
+ }
+ .scrollContentBackground(.hidden)
+ .background(Color.black)
+ .navigationTitle("Compare Domains")
+ }
+
+ private func domainPicker(_ label: String, selection: Binding<UUID?>) -> some View {
+ Picker(label, selection: selection) {
+ Text("Select a domain").tag(UUID?.none)
+ ForEach(states) { state in
+ Text(state.trackedDomain.domain).tag(Optional(state.trackedDomain.id))
+ }
+ }
+ }
+}