@@ -32,8 +32,8 @@ |
||
| 32 | 32 |
</TestAction> |
| 33 | 33 |
<LaunchAction |
| 34 | 34 |
buildConfiguration = "Debug" |
| 35 |
- selectedDebuggerIdentifier = "" |
|
| 36 |
- selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn" |
|
| 35 |
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
|
| 36 |
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
|
| 37 | 37 |
launchStyle = "0" |
| 38 | 38 |
useCustomWorkingDirectory = "NO" |
| 39 | 39 |
ignoresPersistentStateOnLaunch = "NO" |
@@ -421,6 +421,9 @@ private struct DataTypeRecordListView: View {
|
||
| 421 | 421 |
let records: [HealthRecordValue] |
| 422 | 422 |
let totalCount: Int |
| 423 | 423 |
let tint: Color |
| 424 |
+ private var showsValueDisclaimer: Bool {
|
|
| 425 |
+ records.contains { ($0.displayValue?.isEmpty ?? true) }
|
|
| 426 |
+ } |
|
| 424 | 427 |
|
| 425 | 428 |
var body: some View {
|
| 426 | 429 |
List {
|
@@ -440,6 +443,11 @@ private struct DataTypeRecordListView: View {
|
||
| 440 | 443 |
.font(.caption) |
| 441 | 444 |
.foregroundStyle(.secondary) |
| 442 | 445 |
} |
| 446 |
+ if showsValueDisclaimer {
|
|
| 447 |
+ Text("For privacy, HealthProbe stores only timestamps and a record fingerprint here (not the raw HealthKit value).")
|
|
| 448 |
+ .font(.caption) |
|
| 449 |
+ .foregroundStyle(.secondary) |
|
| 450 |
+ } |
|
| 443 | 451 |
} |
| 444 | 452 |
|
| 445 | 453 |
Section(title) {
|
@@ -531,20 +539,34 @@ private struct DataTypeRecordRow: View {
|
||
| 531 | 539 |
let tint: Color |
| 532 | 540 |
|
| 533 | 541 |
var body: some View {
|
| 542 |
+ let recordDate = record.startDate.formatted(.dateTime.year().month().day()) |
|
| 543 |
+ let startTime = record.startDate.formatted(.dateTime.hour().minute()) |
|
| 544 |
+ let endTime = record.endDate.formatted(.dateTime.hour().minute()) |
|
| 545 |
+ let timeRange = (startTime == endTime) ? startTime : "\(startTime)–\(endTime)" |
|
| 546 |
+ |
|
| 534 | 547 |
HStack(spacing: 12) {
|
| 535 | 548 |
VStack(alignment: .leading, spacing: 2) {
|
| 536 |
- Text(record.displayValue ?? "Value unavailable") |
|
| 537 |
- .font(.subheadline) |
|
| 538 |
- .foregroundStyle(record.displayValue == nil ? .secondary : .primary) |
|
| 539 |
- Text(record.startDate, format: .dateTime.year().month().day().hour().minute()) |
|
| 549 |
+ if let displayValue = record.displayValue, !displayValue.isEmpty {
|
|
| 550 |
+ Text(displayValue) |
|
| 551 |
+ .font(.subheadline) |
|
| 552 |
+ .foregroundStyle(.primary) |
|
| 553 |
+ } else {
|
|
| 554 |
+ Text("No value stored")
|
|
| 555 |
+ .font(.subheadline) |
|
| 556 |
+ .foregroundStyle(.secondary) |
|
| 557 |
+ } |
|
| 558 |
+ Text("\(recordDate) • \(timeRange)")
|
|
| 540 | 559 |
.font(.caption) |
| 541 | 560 |
.foregroundStyle(.secondary) |
| 542 | 561 |
} |
| 543 | 562 |
|
| 544 | 563 |
Spacer() |
| 545 |
- Text(record.endDate, format: .dateTime.hour().minute()) |
|
| 546 |
- .font(.caption) |
|
| 547 |
- .foregroundStyle(tint) |
|
| 564 |
+ if startTime != endTime {
|
|
| 565 |
+ Text(endTime) |
|
| 566 |
+ .font(.caption) |
|
| 567 |
+ .foregroundStyle(tint) |
|
| 568 |
+ .accessibilityLabel("End \(endTime)")
|
|
| 569 |
+ } |
|
| 548 | 570 |
} |
| 549 | 571 |
.padding(.vertical, 2) |
| 550 | 572 |
.accessibilityElement(children: .combine) |