1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
import SwiftUI
private enum RootTab: Hashable {
case dashboard
case audit
case history
case inspect
case settings
}
struct RootTabView: View {
@Bindable var viewModel: DomainViewModel
@State private var purchaseService = PurchaseService.shared
@State private var intentRouter = DomainDigIntentRouter.shared
@State private var detailDomain: TrackedDomain?
@State private var selectedTab: RootTab = FeatureAccessService.currentTier == .free ? .inspect : .dashboard
var body: some View {
let _ = purchaseService.currentTier
TabView(selection: $selectedTab) {
NavigationStack {
DashboardView(viewModel: viewModel)
}
.tabItem {
Label("Dashboard", systemImage: "square.grid.2x2")
}
.tag(RootTab.dashboard)
NavigationStack {
AuditListView(viewModel: viewModel)
}
.tabItem {
Label("Audit", systemImage: "checklist")
}
.tag(RootTab.audit)
NavigationStack {
HistoryView(viewModel: viewModel)
}
.tabItem {
Label("History", systemImage: "clock.arrow.trianglehead.counterclockwise.rotate.90")
}
.tag(RootTab.history)
ContentView(viewModel: viewModel)
.tabItem {
Label("Inspect", systemImage: "magnifyingglass")
}
.tag(RootTab.inspect)
NavigationStack {
SettingsView(viewModel: viewModel)
}
.tabItem {
Label("Settings", systemImage: "gearshape")
}
.tag(RootTab.settings)
}
.sheet(isPresented: Binding(
get: { viewModel.isPaywallPresented },
set: { viewModel.isPaywallPresented = $0 }
)) {
PaywallView()
}
.alert(item: Binding(
get: { viewModel.upgradePrompt },
set: { viewModel.upgradePrompt = $0 }
)) { prompt in
Alert(
title: Text(prompt.title),
message: Text(prompt.message),
primaryButton: .default(Text("Open Paywall")) {
viewModel.upgradePrompt = nil
viewModel.isPaywallPresented = true
},
secondaryButton: .cancel(Text("Continue")) {
viewModel.upgradePrompt = nil
}
)
}
.onChange(of: purchaseService.currentTier) { _, newValue in
if newValue != .free, selectedTab == .inspect, viewModel.trackedDomains.isEmpty == false {
selectedTab = .dashboard
}
}
.sheet(item: $detailDomain) { trackedDomain in
NavigationStack {
TrackedDomainDetailView(viewModel: viewModel, trackedDomain: trackedDomain)
}
}
.onOpenURL { url in
guard let action = DomainDigDeepLink.action(from: url) else { return }
perform(action)
}
.onChange(of: intentRouter.pendingAction) { _, action in
consume(action)
}
.task {
consume(intentRouter.pendingAction)
}
}
private func consume(_ action: DomainDigDeepLink.Action?) {
guard let action else { return }
intentRouter.pendingAction = nil
perform(action)
}
private func perform(_ action: DomainDigDeepLink.Action) {
switch action {
case let .inspect(domain):
viewModel.domain = domain
selectedTab = .inspect
viewModel.run()
case let .watch(domain):
// On success show the dashboard (where tracked domains live); on
// failure stay put so the upgrade/paywall alert surfaces in place.
if viewModel.trackDomain(domain: domain, availabilityStatus: nil) {
selectedTab = .dashboard
}
case let .detail(domain):
// Open the tracked domain's detail (e.g. from a widget tap). If it is
// no longer tracked, fall back to inspecting it.
if let tracked = viewModel.trackedDomains.first(
where: { $0.domain.caseInsensitiveCompare(domain) == .orderedSame }
) {
detailDomain = tracked
} else {
perform(.inspect(domain))
}
case .sweep:
selectedTab = .dashboard
viewModel.refreshAllTrackedDomains()
}
}
}
|