83 lines
2.6 KiB
Swift
83 lines
2.6 KiB
Swift
import SwiftUI
|
|
import ProxyCore
|
|
import GRDB
|
|
|
|
struct DomainDetailView: View {
|
|
let domain: String
|
|
|
|
@State private var requests: [CapturedTraffic] = []
|
|
@State private var searchText = ""
|
|
@State private var filterChips: [FilterChip] = [
|
|
FilterChip(label: "JSON"),
|
|
FilterChip(label: "Form"),
|
|
FilterChip(label: "HTTP"),
|
|
FilterChip(label: "HTTPS"),
|
|
]
|
|
@State private var observation: AnyDatabaseCancellable?
|
|
|
|
private let trafficRepo = TrafficRepository()
|
|
|
|
var filteredRequests: [CapturedTraffic] {
|
|
var result = requests
|
|
|
|
if !searchText.isEmpty {
|
|
result = result.filter { $0.url.localizedCaseInsensitiveContains(searchText) }
|
|
}
|
|
|
|
let activeFilters = filterChips.filter(\.isSelected).map(\.label)
|
|
if !activeFilters.isEmpty {
|
|
result = result.filter { request in
|
|
for filter in activeFilters {
|
|
switch filter {
|
|
case "JSON":
|
|
if request.responseContentType?.contains("json") == true { return true }
|
|
case "Form":
|
|
if request.requestContentType?.contains("form") == true { return true }
|
|
case "HTTP":
|
|
if request.scheme == "http" { return true }
|
|
case "HTTPS":
|
|
if request.scheme == "https" { return true }
|
|
default: break
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(spacing: 0) {
|
|
FilterChipsView(chips: $filterChips)
|
|
.padding(.vertical, 8)
|
|
|
|
List {
|
|
ForEach(filteredRequests) { request in
|
|
NavigationLink(value: request.id) {
|
|
TrafficRowView(traffic: request)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.searchable(text: $searchText)
|
|
.navigationTitle(domain)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.navigationDestination(for: Int64?.self) { id in
|
|
if let id {
|
|
RequestDetailView(trafficId: id)
|
|
}
|
|
}
|
|
.task {
|
|
observation = trafficRepo.observeTraffic(forDomain: domain)
|
|
.start(in: DatabaseManager.shared.dbPool) { error in
|
|
print("Observation error: \(error)")
|
|
} onChange: { newRequests in
|
|
withAnimation {
|
|
requests = newRequests
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|