Showing 1 changed files with 57 additions and 25 deletions
+57 -25
USB Meter/Views/MeterDetailView.swift
@@ -1,5 +1,7 @@
1 1
 import SwiftUI
2 2
 
3
+/// Offline meter view - shows meter information when not connected.
4
+/// Uses same tab-based layout as MeterView but filtered to available operations.
3 5
 struct MeterDetailView: View {
4 6
     @EnvironmentObject private var appData: AppData
5 7
     @Environment(\.dismiss) private var dismiss
@@ -8,36 +10,67 @@ struct MeterDetailView: View {
8 10
 
9 11
     let meterSummary: AppData.MeterSummary
10 12
 
13
+    private let meterColor = Color.orange
14
+
11 15
     var body: some View {
12
-        ScrollView {
13
-            VStack(spacing: 18) {
14
-                headerCard
15
-                statusCard
16
-                identifiersCard
16
+        GeometryReader { proxy in
17
+            let landscape = proxy.size.width > proxy.size.height
18
+
19
+            VStack(spacing: 0) {
20
+                // Compact header matching online meters
21
+                HStack(spacing: 12) {
22
+                    Text(meterSummary.displayName.isEmpty ? "Meter" : meterSummary.displayName)
23
+                        .font(.headline)
24
+                        .lineLimit(1)
25
+
26
+                    Spacer()
27
+
28
+                    Button("Edit") {
29
+                        editorVisibility = true
30
+                    }
31
+                    .font(.body.weight(.semibold))
32
+
33
+                    Button(role: .destructive) {
34
+                        deleteConfirmationVisibility = true
35
+                    } label: {
36
+                        Image(systemName: "trash")
37
+                    }
38
+                    .font(.body.weight(.semibold))
39
+                }
40
+                .padding(.horizontal, 16)
41
+                .padding(.vertical, 10)
42
+                .background(
43
+                    Rectangle()
44
+                        .fill(.ultraThinMaterial)
45
+                        .ignoresSafeArea(edges: .top)
46
+                )
47
+                .overlay(alignment: .bottom) {
48
+                    Rectangle()
49
+                        .fill(Color.secondary.opacity(0.12))
50
+                        .frame(height: 1)
51
+                }
52
+
53
+                // Content
54
+                ScrollView {
55
+                    VStack(spacing: 18) {
56
+                        headerCard
57
+                        statusCard
58
+                        identifiersCard
59
+                    }
60
+                    .padding()
61
+                }
62
+                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
17 63
             }
18
-            .padding()
19 64
         }
20 65
         .background(
21 66
             LinearGradient(
22
-                colors: [meterSummary.tint.opacity(0.18), Color.clear],
67
+                colors: [meterColor.opacity(0.18), Color.clear],
23 68
                 startPoint: .topLeading,
24 69
                 endPoint: .bottomTrailing
25 70
             )
26 71
             .ignoresSafeArea()
27 72
         )
28
-        .navigationTitle(meterSummary.displayName)
29
-        .toolbar {
30
-            ToolbarItemGroup(placement: .primaryAction) {
31
-                Button("Edit") {
32
-                    editorVisibility = true
33
-                }
34
-                Button(role: .destructive) {
35
-                    deleteConfirmationVisibility = true
36
-                } label: {
37
-                    Image(systemName: "trash")
38
-                }
39
-            }
40
-        }
73
+        .navigationBarHidden(true)
41 74
         .sheet(isPresented: $editorVisibility) {
42 75
             MeterEditorSheetView(existingMeterSummary: meterSummary)
43 76
                 .environmentObject(appData)
@@ -69,7 +102,7 @@ struct MeterDetailView: View {
69 102
         }
70 103
         .frame(maxWidth: .infinity, alignment: .leading)
71 104
         .padding(18)
72
-        .meterCard(tint: meterSummary.tint, fillOpacity: 0.22, strokeOpacity: 0.28, cornerRadius: 20)
105
+        .meterCard(tint: meterColor, fillOpacity: 0.22, strokeOpacity: 0.28, cornerRadius: 20)
73 106
     }
74 107
 
75 108
     private var statusCard: some View {
@@ -79,12 +112,12 @@ struct MeterDetailView: View {
79 112
                     .font(.headline)
80 113
                 ContextInfoButton(
81 114
                     title: "Status",
82
-                    message: "The meter is not currently connected. Bring it within Bluetooth range or wake it up to open live diagnostics."
115
+                    message: "This meter is offline. Bring it within Bluetooth range to connect and view live data."
83 116
                 )
84 117
             }
85 118
             HStack(spacing: 8) {
86 119
                 Circle()
87
-                    .fill(meterSummary.tint)
120
+                    .fill(Color.red)
88 121
                     .frame(width: 10, height: 10)
89 122
                 Text("Offline")
90 123
                     .font(.caption.weight(.semibold))
@@ -93,7 +126,7 @@ struct MeterDetailView: View {
93 126
         }
94 127
         .frame(maxWidth: .infinity, alignment: .leading)
95 128
         .padding(18)
96
-        .meterCard(tint: meterSummary.tint, fillOpacity: 0.16, strokeOpacity: 0.22, cornerRadius: 18)
129
+        .meterCard(tint: meterColor, fillOpacity: 0.16, strokeOpacity: 0.22, cornerRadius: 18)
97 130
     }
98 131
 
99 132
     private var identifiersCard: some View {
@@ -134,7 +167,6 @@ struct MeterDetailView_Previews: PreviewProvider {
134 167
                 meter: nil
135 168
             )
136 169
         )
137
-        .environmentObject(appData)
138 170
     }
139 171
 }
140 172