@@ -24,6 +24,7 @@ final class DashboardViewModel {
|
||
| 24 | 24 |
var ambiguousDisappearedMetrics: [AmbiguousDisappearedMetric] = [] |
| 25 | 25 |
var latestArchiveObservation: CachedArchiveObservationRow? |
| 26 | 26 |
var archiveObservationRows: [CachedArchiveObservationRow] = [] |
| 27 |
+ var isLoadingArchiveStatus = false |
|
| 27 | 28 |
var archiveHealthStatus: CachedArchiveHealthStatus? |
| 28 | 29 |
var archiveCacheError: String? |
| 29 | 30 |
|
@@ -321,6 +322,8 @@ final class DashboardViewModel {
|
||
| 321 | 322 |
|
| 322 | 323 |
@MainActor |
| 323 | 324 |
func loadArchiveCacheStatus() async {
|
| 325 |
+ isLoadingArchiveStatus = true |
|
| 326 |
+ defer { isLoadingArchiveStatus = false }
|
|
| 324 | 327 |
do {
|
| 325 | 328 |
archiveObservationRows = try await SQLiteHealthArchiveStore.shared.observationRows(limit: 2) |
| 326 | 329 |
latestArchiveObservation = archiveObservationRows.first |
@@ -10,6 +10,7 @@ final class DataTypesViewModel {
|
||
| 10 | 10 |
var filter: DiffFilter = .all |
| 11 | 11 |
var comparisonMode: ComparisonMode = .previous |
| 12 | 12 |
var observationRows: [CachedArchiveObservationRow] = [] |
| 13 |
+ var hasLoadedObservationRows = false |
|
| 13 | 14 |
var observationRowsError: String? |
| 14 | 15 |
var archiveDiffs: [TypeDiff]? |
| 15 | 16 |
var archiveDiffError: String? |
@@ -43,9 +44,11 @@ final class DataTypesViewModel {
|
||
| 43 | 44 |
func loadArchiveRows(limit: Int = 200) async {
|
| 44 | 45 |
do {
|
| 45 | 46 |
observationRows = try await SQLiteHealthArchiveStore.shared.observationRows(limit: limit) |
| 47 |
+ hasLoadedObservationRows = true |
|
| 46 | 48 |
observationRowsError = nil |
| 47 | 49 |
} catch {
|
| 48 | 50 |
observationRows = [] |
| 51 |
+ hasLoadedObservationRows = true |
|
| 49 | 52 |
observationRowsError = error.localizedDescription |
| 50 | 53 |
} |
| 51 | 54 |
} |
@@ -26,6 +26,7 @@ final class SnapshotsViewModel {
|
||
| 26 | 26 |
var comparisonMode: ComparisonMode = .previous |
| 27 | 27 |
var selectedBaselineObservationID: Int64? |
| 28 | 28 |
var archiveRows: [CachedArchiveObservationRow]? |
| 29 |
+ var hasLoadedArchiveRows = false |
|
| 29 | 30 |
var archiveRowsError: String? |
| 30 | 31 |
|
| 31 | 32 |
@MainActor |
@@ -33,9 +34,11 @@ final class SnapshotsViewModel {
|
||
| 33 | 34 |
do {
|
| 34 | 35 |
let rows = try await SQLiteHealthArchiveStore.shared.observationRows(limit: limit) |
| 35 | 36 |
archiveRows = rows.isEmpty ? nil : rows |
| 37 |
+ hasLoadedArchiveRows = true |
|
| 36 | 38 |
archiveRowsError = nil |
| 37 | 39 |
} catch {
|
| 38 | 40 |
archiveRows = nil |
| 41 |
+ hasLoadedArchiveRows = true |
|
| 39 | 42 |
archiveRowsError = error.localizedDescription |
| 40 | 43 |
} |
| 41 | 44 |
} |
@@ -1158,6 +1158,9 @@ struct DashboardView: View {
|
||
| 1158 | 1158 |
Text("\(latestArchiveObservation.trackedTypeCount)")
|
| 1159 | 1159 |
.foregroundStyle(.secondary) |
| 1160 | 1160 |
} |
| 1161 |
+ } else if viewModel.isLoadingArchiveStatus {
|
|
| 1162 |
+ Label("Loading archive observations", systemImage: "clock.arrow.circlepath")
|
|
| 1163 |
+ .foregroundStyle(.secondary) |
|
| 1161 | 1164 |
} else {
|
| 1162 | 1165 |
Label("No archive observations yet", systemImage: "camera.viewfinder")
|
| 1163 | 1166 |
.foregroundStyle(.secondary) |
@@ -1199,7 +1202,7 @@ struct DashboardView: View {
|
||
| 1199 | 1202 |
Text("\(archiveHealthStatus.cacheSchemaVersion)")
|
| 1200 | 1203 |
.foregroundStyle(.secondary) |
| 1201 | 1204 |
} |
| 1202 |
- } else {
|
|
| 1205 |
+ } else if !viewModel.isLoadingArchiveStatus {
|
|
| 1203 | 1206 |
Label("Archive cache not built", systemImage: "externaldrive.badge.questionmark")
|
| 1204 | 1207 |
.font(.caption) |
| 1205 | 1208 |
.foregroundStyle(.secondary) |
@@ -28,7 +28,11 @@ struct DataTypesView: View {
|
||
| 28 | 28 |
var body: some View {
|
| 29 | 29 |
NavigationStack {
|
| 30 | 30 |
Group {
|
| 31 |
- if displayedSnapshotContexts.count < 2 {
|
|
| 31 |
+ if !viewModel.hasLoadedObservationRows {
|
|
| 32 |
+ ContentUnavailableView {
|
|
| 33 |
+ Label("Loading data types", systemImage: "waveform.path.ecg")
|
|
| 34 |
+ } |
|
| 35 |
+ } else if displayedSnapshotContexts.count < 2 {
|
|
| 32 | 36 |
EmptyStateView( |
| 33 | 37 |
icon: "waveform.path.ecg", |
| 34 | 38 |
title: "Not Enough Data", |
@@ -25,7 +25,11 @@ struct SnapshotsView: View {
|
||
| 25 | 25 |
var body: some View {
|
| 26 | 26 |
NavigationStack {
|
| 27 | 27 |
Group {
|
| 28 |
- if !hasTimelineRows {
|
|
| 28 |
+ if !viewModel.hasLoadedArchiveRows {
|
|
| 29 |
+ ContentUnavailableView {
|
|
| 30 |
+ Label("Loading snapshots", systemImage: "clock.arrow.circlepath")
|
|
| 31 |
+ } |
|
| 32 |
+ } else if !hasTimelineRows {
|
|
| 29 | 33 |
EmptyStateView( |
| 30 | 34 |
icon: "clock.arrow.circlepath", |
| 31 | 35 |
title: "No Snapshots", |