import SwiftUI struct ContentView: View { @EnvironmentObject var sdk: SDKManager @State private var userId = "test-user-001" @State private var fileKey = "" var body: some View { NavigationView { List { statusSection scanSection deviceSection fileSection logSection } .navigationTitle("BLE SDK Test") } } // MARK: - Status private var statusSection: some View { Section("Status") { HStack { Text("Connection") Spacer() Text(sdk.btState) .foregroundStyle(sdk.btState == "connected" ? .green : .secondary) .fontWeight(.medium) } if let error = sdk.error { HStack { Image(systemName: "exclamationmark.triangle.fill") .foregroundStyle(.red) Text(error) .foregroundStyle(.red) .font(.caption) } } HStack { Text("SDK Ready") Spacer() Image(systemName: sdk.isSDKReady ? "checkmark.circle.fill" : "xmark.circle") .foregroundStyle(sdk.isSDKReady ? .green : .red) } } } // MARK: - Scan private var scanSection: some View { Section("Scan") { HStack { Button("Scan") { sdk.scan() } .buttonStyle(.borderedProminent) .disabled(sdk.btState == "scanning") Button("Stop") { sdk.stopScan() } .buttonStyle(.bordered) .disabled(sdk.btState != "scanning") } if sdk.discoveredDevices.isEmpty && sdk.btState == "scanning" { HStack { ProgressView() Text("Searching...") .foregroundStyle(.secondary) } } ForEach(sdk.discoveredDevices) { device in Button { sdk.stopScan() sdk.connect(deviceId: device.id) } label: { HStack { VStack(alignment: .leading) { Text(device.name) .font(.body) Text(device.id) .font(.caption2) .foregroundStyle(.secondary) } Spacer() Text("\(device.rssi) dBm") .font(.caption) .foregroundStyle(.secondary) } } } } } // MARK: - Device private var deviceSection: some View { Section("Device") { if sdk.btState == "connected" { if let device = sdk.connectedDevice { LabeledContent("Name", value: device["name"] as? String ?? "—") LabeledContent("ID", value: device["id"] as? String ?? "—") } LabeledContent("Version", value: sdk.version.isEmpty ? "—" : sdk.version) if let info = sdk.deviceInfo { LabeledContent("Brand", value: info.brand) LabeledContent("Screen", value: info.screenSize) LabeledContent("Battery", value: "\(info.batteryLevel)%") LabeledContent("Storage", value: formatStorage(free: info.freeSpace, total: info.totalSpace)) } HStack(spacing: 12) { Button("Get Info") { sdk.getDeviceInfo() } .buttonStyle(.bordered) Button("Get Version") { sdk.getVersion() } .buttonStyle(.bordered) } HStack { TextField("User ID", text: $userId) .textFieldStyle(.roundedBorder) Button("Bind") { sdk.bind(userId: userId) } .buttonStyle(.bordered) } HStack(spacing: 12) { Button("Unbind") { sdk.unbind(userId: userId) } .buttonStyle(.bordered) Button("Disconnect") { sdk.disconnect() } .buttonStyle(.bordered) .tint(.red) } } else if sdk.btState == "connecting" { HStack { ProgressView() Text("Connecting...") } } else { Text("No device connected") .foregroundStyle(.secondary) } } } // MARK: - File private var fileSection: some View { Section("File Transfer") { if sdk.btState == "connected" { if sdk.transferProgress > 0 { VStack(alignment: .leading) { Text("Transfer: \(sdk.transferProgress)%") .font(.caption) ProgressView(value: Double(sdk.transferProgress), total: 100) } } HStack { TextField("File key to delete", text: $fileKey) .textFieldStyle(.roundedBorder) Button("Delete") { sdk.deleteFile(key: fileKey) } .buttonStyle(.bordered) .tint(.red) .disabled(fileKey.isEmpty) } } else { Text("Connect a device first") .foregroundStyle(.secondary) } } } // MARK: - Log private var logSection: some View { Section("Event Log (\(sdk.logs.count))") { ForEach(sdk.logs.prefix(50)) { entry in VStack(alignment: .leading, spacing: 2) { Text(entry.message) .font(.caption) Text(entry.time, style: .time) .font(.caption2) .foregroundStyle(.tertiary) } } if sdk.logs.isEmpty { Text("No events yet") .foregroundStyle(.secondary) } } } // MARK: - Helpers private func formatStorage(free: Int, total: Int) -> String { let freeMB = free / 1_048_576 let totalMB = total / 1_048_576 return "\(freeMB)MB / \(totalMB)MB" } }