1 contributor
//
// SidebarView.swift
// USB Meter
//
import SwiftUI
import Combine
struct SidebarView: View {
@EnvironmentObject private var appData: AppData
@State private var isHelpExpanded = false
@State private var dismissedAutoHelpReason: SidebarHelpReason?
@State private var now = Date()
private let helpRefreshTimer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
private let noDevicesHelpDelay: TimeInterval = 12
var body: some View {
SidebarListView(backgroundTint: appData.bluetoothManager.managerState.color) {
usbMetersSection
} helpSection: {
helpSection
} debugSection: {
debugSection
}
.onAppear {
appData.bluetoothManager.start()
now = Date()
}
.onReceive(helpRefreshTimer) { currentDate in
now = currentDate
}
.onChange(of: activeHelpAutoReason) { newReason in
if newReason == nil {
dismissedAutoHelpReason = nil
}
}
}
private var usbMetersSection: some View {
SidebarUSBMetersSectionView(
meters: appData.meterSummaries,
managerState: appData.bluetoothManager.managerState,
hasLiveMeters: appData.meters.isEmpty == false,
scanStartedAt: appData.bluetoothManager.scanStartedAt,
now: now,
noDevicesHelpDelay: noDevicesHelpDelay
)
}
private var helpSection: some View {
SidebarHelpSectionView(
activeReason: activeHelpAutoReason,
isExpanded: helpIsExpanded,
bluetoothStatusTint: appData.bluetoothManager.managerState.color,
bluetoothStatusText: bluetoothStatusText,
cloudSyncHelpTitle: appData.cloudAvailability.helpTitle,
cloudSyncHelpMessage: appData.cloudAvailability.helpMessage,
onToggle: toggleHelpSection,
onOpenSettings: openSettings
) {
appData.bluetoothManager.managerState.helpView
} deviceHelpDestination: {
DeviceHelpView()
}
}
private var debugSection: some View {
SidebarDebugSectionView()
}
private var bluetoothStatusText: String {
switch appData.bluetoothManager.managerState {
case .poweredOff:
return "Off"
case .poweredOn:
return "On"
case .resetting:
return "Resetting"
case .unauthorized:
return "Unauthorized"
case .unknown:
return "Unknown"
case .unsupported:
return "Unsupported"
@unknown default:
return "Other"
}
}
private var helpIsExpanded: Bool {
isHelpExpanded || shouldAutoExpandHelp
}
private var shouldAutoExpandHelp: Bool {
guard let activeHelpAutoReason else {
return false
}
return dismissedAutoHelpReason != activeHelpAutoReason
}
private var activeHelpAutoReason: SidebarHelpReason? {
SidebarAutoHelpResolver.activeReason(
managerState: appData.bluetoothManager.managerState,
cloudAvailability: appData.cloudAvailability,
hasLiveMeters: appData.meters.isEmpty == false,
scanStartedAt: appData.bluetoothManager.scanStartedAt,
now: now,
noDevicesHelpDelay: noDevicesHelpDelay
)
}
private func toggleHelpSection() {
withAnimation(.easeInOut(duration: 0.22)) {
if shouldAutoExpandHelp {
dismissedAutoHelpReason = activeHelpAutoReason
isHelpExpanded = false
} else {
isHelpExpanded.toggle()
}
}
}
private func openSettings() {
guard let settingsURL = URL(string: UIApplication.openSettingsURLString) else {
return
}
UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil)
}
}