TempTrack-iOS/TempTrack/Views/DeviceInfoView.swift

191 lines
6.1 KiB
Swift
Raw Normal View History

2023-06-03 08:15:00 +02:00
import SwiftUI
import SFSafeSymbols
private let df: DateFormatter = {
let df = DateFormatter()
df.locale = .current
df.dateStyle = .short
df.timeStyle = .short
return df
}()
struct DeviceInfoView: View {
private let storageWarnBytes = 500
let info: DeviceInfo
@Binding
var isPresented: Bool
2023-06-03 08:15:00 +02:00
private var runTimeString: String {
let number = info.numberOfSecondsRunning
guard number >= 60 else {
2023-06-13 17:14:57 +02:00
return "\(number) s"
2023-06-03 08:15:00 +02:00
}
let minutes = number / 60
guard minutes > 1 else {
2023-06-13 17:14:57 +02:00
return "1 min"
2023-06-03 08:15:00 +02:00
}
guard minutes >= 60 else {
2023-06-13 17:14:57 +02:00
return "\(minutes) min"
2023-06-03 08:15:00 +02:00
}
let hours = minutes / 60
guard hours > 1 else {
return "1 hour"
}
guard hours >= 60 else {
return "\(hours) hours"
}
let days = hours / 24
guard days > 1 else {
return "1 day"
}
return "\(days) days"
}
private var nextUpdateText: String {
let secs = Int(info.nextMeasurement.timeIntervalSinceNow.rounded())
guard secs > 1 else {
return "Now"
}
2023-06-13 17:14:57 +02:00
return "In \(secs) s"
2023-06-03 08:15:00 +02:00
}
private var storageIcon: SFSymbol {
if info.storageSize - info.numberOfRecordedBytes < storageWarnBytes {
return .externaldriveTrianglebadgeExclamationmark
}
return .externaldrive
}
private var storageText: String {
if info.storageSize <= 0 {
return "\(info.numberOfRecordedBytes)"
}
return "\(info.numberOfRecordedBytes) / \(info.storageSize) Bytes (\(info.storageFillPercentage) %)"
}
func sensorView(_ sensor: TemperatureSensor?, id: Int) -> some View {
2023-06-08 14:57:40 +02:00
VStack(alignment: .leading, spacing: 5) {
Text("Sensor \(id)")
.font(.headline)
if let sensor {
HStack {
Image(systemSymbol: sensor.temperatureIcon)
.frame(width: 30)
2023-06-13 17:14:57 +02:00
Text("\(sensor.temperatureText) (\(sensor.updateText))")
2023-06-08 14:57:40 +02:00
}
HStack {
Image(systemSymbol: .tag)
.frame(width: 30)
Text(sensor.hexAddress)
}
} else {
HStack {
Image(systemSymbol: .thermometerMediumSlash)
.frame(width: 30)
Text("Not connected")
}
2023-06-03 08:15:00 +02:00
}
}
}
var updateText: String {
2023-06-08 14:57:40 +02:00
guard info.receivedDate.secondsToNow > 3 else {
return "Updated Now"
}
return "Updated \(info.receivedDate.timePassedText)"
}
2023-06-08 14:57:40 +02:00
var clockOffsetText: String {
guard info.hasDeviceStartTimeSet else {
return "Clock not synchronized"
}
let offset = info.clockOffset.roundedInt
guard abs(offset) > 1 else {
return "No clock offset"
}
2023-06-13 17:14:57 +02:00
return "Offset: \(offset) s"
2023-06-08 14:57:40 +02:00
}
2023-06-03 08:15:00 +02:00
var body: some View {
2023-06-08 14:57:40 +02:00
NavigationView {
2023-06-03 08:15:00 +02:00
VStack(alignment: .leading, spacing: 5) {
2023-06-08 14:57:40 +02:00
VStack(alignment: .leading, spacing: 5) {
2023-06-13 17:14:57 +02:00
Text("System")
2023-06-08 14:57:40 +02:00
.font(.headline)
HStack {
Image(systemSymbol: .power)
.frame(width: 30)
2023-06-13 17:14:57 +02:00
Text("\(df.string(from: info.deviceStartTime)) (\(runTimeString))")
2023-06-08 14:57:40 +02:00
Spacer()
}
HStack {
Image(systemSymbol: .clockBadgeExclamationmark)
.frame(width: 30)
Text(clockOffsetText)
}
HStack {
2023-06-13 17:14:57 +02:00
Image(systemSymbol: .autostartstop)
2023-06-08 14:57:40 +02:00
.frame(width: 30)
2023-06-13 17:14:57 +02:00
Text("Wakeup: \(info.wakeupReason.text)")
2023-06-08 14:57:40 +02:00
Spacer()
}
2023-06-13 17:14:57 +02:00
}
VStack(alignment: .leading, spacing: 5) {
Text("Recording")
.font(.headline)
2023-06-08 14:57:40 +02:00
HStack {
2023-06-13 17:14:57 +02:00
Image(systemSymbol: .stopwatch)
2023-06-08 14:57:40 +02:00
.frame(width: 30)
2023-06-13 17:14:57 +02:00
Text("\(nextUpdateText) (Every \(info.measurementInterval) s)")
2023-06-08 14:57:40 +02:00
Spacer()
}
2023-06-03 08:15:00 +02:00
}
2023-06-08 14:57:40 +02:00
VStack(alignment: .leading, spacing: 5) {
Text("Storage")
.font(.headline)
HStack {
Image(systemSymbol: .speedometer)
.frame(width: 30)
Text("\(info.numberOfStoredMeasurements) Measurements (\(info.totalNumberOfMeasurements) total)")
}
HStack {
Image(systemSymbol: storageIcon)
.frame(width: 30)
Text(storageText)
}
HStack {
Image(systemSymbol: .iphoneAndArrowForward)
.frame(width: 30)
Text("\(info.transferBlockSize) Byte Block Size")
}
2023-06-03 08:15:00 +02:00
}
2023-06-08 14:57:40 +02:00
sensorView(info.sensor0, id: 0)
sensorView(info.sensor1, id: 1)
Spacer()
2023-06-03 08:15:00 +02:00
HStack {
Spacer()
2023-06-08 14:57:40 +02:00
TimelineView(.periodic(from: Date(), by: 1)) { context in
Text(updateText)
.font(.footnote)
.textCase(.uppercase)
}
2023-06-03 08:15:00 +02:00
Spacer()
}
}
2023-06-08 14:57:40 +02:00
.padding()
.navigationTitle("Device Info")
.navigationBarTitleDisplayMode(.large)
}
2023-06-03 08:15:00 +02:00
}
}
struct DeviceInfoView_Previews: PreviewProvider {
static var previews: some View {
DeviceInfoView(info: .mock, isPresented: .constant(true))
2023-06-03 08:15:00 +02:00
}
}