TempTrack-iOS/TempTrack/Views/TransferView.swift

181 lines
5.3 KiB
Swift
Raw Normal View History

import SwiftUI
import SFSafeSymbols
struct TransferView: View {
private let storageWarnBytes = 500
let bluetoothClient: BluetoothDevice
2023-07-03 13:28:51 +02:00
@Binding
var info: DeviceInfo?
@EnvironmentObject
var storage: PersistentStorage
2023-07-03 13:28:51 +02:00
@EnvironmentObject
var transfer: TransferHandler
private var storageIcon: SFSymbol {
2023-07-03 13:28:51 +02:00
guard let info else {
return .externaldrive
}
if info.storageSize - info.numberOfRecordedBytes < storageWarnBytes {
return .externaldriveTrianglebadgeExclamationmark
}
return .externaldrive
}
private var measurementsText: String {
2023-07-03 13:28:51 +02:00
guard let info else {
return "No measurements"
}
return "\(info.numberOfStoredMeasurements) measurements (\(info.time.totalNumberOfMeasurements) total)"
}
private var storageText: String {
2023-07-03 13:28:51 +02:00
guard let info else {
return "No data"
}
if info.storageSize <= 0 {
return "\(info.numberOfRecordedBytes) Bytes"
}
return "\(info.numberOfRecordedBytes) / \(info.storageSize) Bytes (\(info.storageFillPercentage) %)"
}
private var transferSizeText: String {
2023-07-03 13:28:51 +02:00
guard let info else {
return "No transfer size"
}
return "\(info.transferBlockSize) Byte Block Size"
}
private var transferByteText: String {
2023-07-03 13:28:51 +02:00
let total = Int(transfer.totalBytes)
guard total > 0 else {
return "No data"
}
2023-07-03 13:28:51 +02:00
return "\(Int(transfer.bytesTransferred)) / \(total) Bytes"
}
private var transferMeasurementText: String {
2023-07-03 13:28:51 +02:00
guard !transfer.measurements.isEmpty else {
return "No measurements"
}
2023-07-03 13:28:51 +02:00
return "\(transfer.measurements.count) measurements"
}
var body: some View {
NavigationView {
VStack {
VStack(alignment: .leading, spacing: 5) {
Text("Storage")
.font(.headline)
IconAndTextView(
icon: .speedometer,
text: measurementsText)
IconAndTextView(
icon: storageIcon,
text: storageText)
IconAndTextView(
icon: .iphoneAndArrowForward,
text: transferSizeText)
}
Button(action: clearStorage) {
Text("Remove recorded data")
}
2023-07-03 13:28:51 +02:00
.disabled(transfer.transferIsRunning)
.padding()
VStack(alignment: .leading, spacing: 5) {
Text("Transfer")
.font(.headline)
2023-07-03 13:28:51 +02:00
ProgressView(value: transfer.bytesTransferred, total: transfer.totalBytes)
.progressViewStyle(.linear)
.padding(.vertical, 5)
IconAndTextView(
icon: .externaldrive,
text: transferByteText)
IconAndTextView(
icon: .speedometer,
text: transferMeasurementText)
}
HStack {
Button(action: transferData) {
Text("Transfer")
}
2023-07-03 13:28:51 +02:00
.disabled(transfer.transferIsRunning)
.padding()
Spacer()
Button(action: saveTransfer) {
Text("Save")
}
2023-07-03 13:28:51 +02:00
.disabled(transfer.transferIsRunning || transfer.measurements.isEmpty)
.padding()
Spacer()
Button(action: discardTransfer) {
Text("Discard")
}
2023-07-03 13:28:51 +02:00
.disabled(transfer.transferIsRunning || transfer.measurements.isEmpty)
.padding()
}
Spacer()
VStack {
}
}
.padding()
.navigationTitle("Data Transfer")
.navigationBarTitleDisplayMode(.large)
}
}
func transferData() {
2023-07-03 13:28:51 +02:00
guard let info else {
return
}
2023-07-03 13:28:51 +02:00
transfer.startTransfer(from: bluetoothClient, with: info, storage: storage)
}
func discardTransfer() {
2023-07-03 13:28:51 +02:00
transfer.discardTransfer()
}
func saveTransfer() {
2023-07-03 13:28:51 +02:00
transfer.saveTransfer(in: storage)
}
func clearStorage() {
2023-07-03 13:28:51 +02:00
guard let byteCount = info?.numberOfRecordedBytes else {
return
}
Task {
guard await bluetoothClient.deleteDeviceData(byteCount: byteCount) else {
log.warning("Failed to delete data")
return
}
log.warning("Device storage cleared")
}
}
}
struct TransferView_Previews: PreviewProvider {
static var previews: some View {
let storage = PersistentStorage(lastMeasurements: TemperatureMeasurement.mockData)
2023-07-03 13:28:51 +02:00
TransferView(bluetoothClient: .init(), info: .constant(.mock))
.environmentObject(storage)
}
}
private extension TemperatureValue {
var relativeValue: Double {
if case .value(let double) = self {
return double
}
return 0
}
}