mirror of
https://github.com/kean/Pulse.git
synced 2026-05-30 21:07:33 +00:00
119 lines
3.8 KiB
Swift
119 lines
3.8 KiB
Swift
// The MIT License (MIT)
|
||
//
|
||
// Copyright (c) 2020-2024 Alexander Grebenyuk (github.com/kean).
|
||
|
||
#if !os(watchOS)
|
||
|
||
import SwiftUI
|
||
import Pulse
|
||
import CoreData
|
||
|
||
@available(iOS 15, visionOS 1.0, *)
|
||
struct NetworkInspectorTransactionView: View {
|
||
@ObservedObject var viewModel: NetworkInspectorTransactionViewModel
|
||
|
||
var body: some View {
|
||
Section {
|
||
contents
|
||
}
|
||
}
|
||
|
||
@ViewBuilder
|
||
private var contents: some View {
|
||
NetworkRequestStatusCell(viewModel: viewModel.statusViewModel)
|
||
#if os(macOS)
|
||
.padding(.bottom, 8)
|
||
#endif
|
||
viewModel.timingViewModel.map(TimingView.init)
|
||
NavigationLink(destination: destintionTransactionDetails) {
|
||
VStack(alignment: .leading, spacing: 4) {
|
||
Text(viewModel.title)
|
||
if let size = viewModel.transferSizeViewModel {
|
||
transferSizeView(size: size)
|
||
}
|
||
}
|
||
}
|
||
NetworkRequestInfoCell(viewModel: viewModel.requestViewModel)
|
||
}
|
||
|
||
@available(iOS 15, visionOS 1.0, *)
|
||
private func transferSizeView(size: NetworkInspectorTransferInfoViewModel) -> some View {
|
||
let font = TextHelper().font(style: .init(role: .subheadline, style: .monospacedDigital, width: .condensed))
|
||
return (Text(Image(systemName: "arrow.down.circle")) +
|
||
Text(" ") +
|
||
Text(size.totalBytesSent) +
|
||
Text(" ") +
|
||
Text(Image(systemName: "arrow.up.circle")) +
|
||
Text(" ") +
|
||
Text(size.totalBytesReceived))
|
||
.lineLimit(1)
|
||
.font(Font(font))
|
||
.foregroundColor(.secondary)
|
||
}
|
||
|
||
private var destintionTransactionDetails: some View {
|
||
NetworkDetailsView(title: "Transaction Details") { viewModel.details() }
|
||
}
|
||
}
|
||
|
||
// MARK: - ViewModel
|
||
|
||
final class NetworkInspectorTransactionViewModel: ObservableObject, Identifiable {
|
||
let id: NSManagedObjectID
|
||
let title: String
|
||
let transaction: NetworkTransactionMetricsEntity
|
||
let statusViewModel: NetworkRequestStatusCellModel
|
||
let timingViewModel: TimingViewModel?
|
||
let requestViewModel: NetworkRequestInfoCellViewModel
|
||
let transferSizeViewModel: NetworkInspectorTransferInfoViewModel?
|
||
let details: () -> NSAttributedString
|
||
|
||
init(transaction: NetworkTransactionMetricsEntity, task: NetworkTaskEntity) {
|
||
self.id = transaction.objectID
|
||
self.title = transaction.fetchType.title
|
||
self.transaction = transaction
|
||
self.statusViewModel = NetworkRequestStatusCellModel(transaction: transaction)
|
||
self.requestViewModel = NetworkRequestInfoCellViewModel(transaction: transaction)
|
||
self.timingViewModel = TimingViewModel(transaction: transaction, task: task)
|
||
|
||
if transaction.fetchType == .networkLoad {
|
||
self.transferSizeViewModel = NetworkInspectorTransferInfoViewModel(transferSize: transaction.transferSize)
|
||
} else {
|
||
self.transferSizeViewModel = nil
|
||
}
|
||
|
||
self.details = {
|
||
let renderer = TextRenderer(options: .sharing)
|
||
let sections = KeyValueSectionViewModel.makeDetails(for: transaction)
|
||
renderer.render(sections)
|
||
return renderer.make()
|
||
}
|
||
}
|
||
}
|
||
|
||
#if DEBUG
|
||
@available(iOS 15, visionOS 1.0, *)
|
||
struct NetworkInspectorTransactionView_Previews: PreviewProvider {
|
||
static var previews: some View {
|
||
NavigationView {
|
||
List {
|
||
ForEach(mockTask.orderedTransactions, id: \.index) {
|
||
NetworkInspectorTransactionView(viewModel: .init(transaction: $0, task: mockTask))
|
||
}
|
||
}.frame(width: 600)
|
||
}
|
||
#if os(macOS)
|
||
.frame(width: 1000, height: 1000)
|
||
#endif
|
||
#if os(watchOS)
|
||
.navigationViewStyle(.stack)
|
||
#endif
|
||
}
|
||
}
|
||
|
||
private let mockTask = LoggerStore.preview.entity(for: .createAPI)
|
||
|
||
#endif
|
||
|
||
#endif
|