Basic display of info
This commit is contained in:
166
TempTrack/Views/DeviceInfoView.swift
Normal file
166
TempTrack/Views/DeviceInfoView.swift
Normal file
@@ -0,0 +1,166 @@
|
||||
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
|
||||
|
||||
private var runTimeString: String {
|
||||
let number = info.numberOfSecondsRunning
|
||||
guard number >= 60 else {
|
||||
return "\(number) seconds"
|
||||
}
|
||||
let minutes = number / 60
|
||||
guard minutes > 1 else {
|
||||
return "1 minute"
|
||||
}
|
||||
guard minutes >= 60 else {
|
||||
return "\(minutes) minutes"
|
||||
}
|
||||
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"
|
||||
}
|
||||
return "In \(secs) seconds"
|
||||
}
|
||||
|
||||
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 {
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("Sensor \(id)")
|
||||
.font(.headline)
|
||||
if let sensor {
|
||||
HStack {
|
||||
Image(systemSymbol: sensor.temperatureIcon)
|
||||
.frame(width: 30)
|
||||
Text(sensor.temperatureText)
|
||||
}
|
||||
HStack {
|
||||
Image(systemSymbol: .arrowTriangle2Circlepath)
|
||||
.frame(width: 30)
|
||||
Text(sensor.updateText)
|
||||
Spacer()
|
||||
}
|
||||
HStack {
|
||||
Image(systemSymbol: .tag)
|
||||
.frame(width: 30)
|
||||
Text(sensor.hexAddress)
|
||||
}
|
||||
} else {
|
||||
HStack {
|
||||
Image(systemSymbol: .thermometerMediumSlash)
|
||||
.frame(width: 30)
|
||||
Text("Not connected")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("Recording")
|
||||
.font(.headline)
|
||||
HStack {
|
||||
Image(systemSymbol: .power)
|
||||
.frame(width: 30)
|
||||
Text(df.string(from: info.deviceStartTime))
|
||||
Spacer()
|
||||
}
|
||||
HStack {
|
||||
Image(systemSymbol: .clock)
|
||||
.frame(width: 30)
|
||||
Text("\(runTimeString)")
|
||||
}
|
||||
HStack {
|
||||
Image(systemSymbol: .stopwatch)
|
||||
.frame(width: 30)
|
||||
Text("Every \(info.measurementInterval) seconds")
|
||||
Spacer()
|
||||
}
|
||||
HStack {
|
||||
Image(systemSymbol: .arrowTriangle2Circlepath)
|
||||
.frame(width: 30)
|
||||
Text(nextUpdateText)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
VStack(alignment: .leading, spacing: 5) {
|
||||
Text("Storage")
|
||||
.font(.headline)
|
||||
HStack {
|
||||
Image(systemSymbol: .speedometer)
|
||||
.frame(width: 30)
|
||||
Text("\(info.numberOfMeasurements) Measurements")
|
||||
}
|
||||
HStack {
|
||||
Image(systemSymbol: storageIcon)
|
||||
.frame(width: 30)
|
||||
Text(storageText)
|
||||
}
|
||||
HStack {
|
||||
Image(systemSymbol: .iphoneAndArrowForward)
|
||||
.frame(width: 30)
|
||||
Text("\(info.transferBlockSize) Byte Block Size")
|
||||
}
|
||||
}
|
||||
sensorView(info.sensor0, id: 0)
|
||||
sensorView(info.sensor1, id: 1)
|
||||
Spacer()
|
||||
HStack {
|
||||
Spacer()
|
||||
Text("Updated \(info.receivedDate.timePassedText)")
|
||||
.font(.footnote)
|
||||
.textCase(.uppercase)
|
||||
Spacer()
|
||||
}
|
||||
}.padding()
|
||||
}
|
||||
}
|
||||
|
||||
struct DeviceInfoView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
DeviceInfoView(info: .mock)
|
||||
.previewLayout(.fixed(width: 375, height: 500))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user