Newer Older
129 lines | 4.033kb
Bogdan Timofte authored a week ago
1
//
2
//  SidebarView.swift
3
//  USB Meter
4
//
5

            
6
import SwiftUI
7
import Combine
8

            
9
struct SidebarView: View {
10
    @EnvironmentObject private var appData: AppData
11
    @State private var isHelpExpanded = false
12
    @State private var dismissedAutoHelpReason: SidebarHelpReason?
13
    @State private var now = Date()
14
    private let helpRefreshTimer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
15
    private let noDevicesHelpDelay: TimeInterval = 12
16

            
17
    var body: some View {
18
        SidebarListView(backgroundTint: appData.bluetoothManager.managerState.color) {
19
            usbMetersSection
20
        } helpSection: {
21
            helpSection
22
        } debugSection: {
23
            debugSection
24
        }
25
        .onAppear {
26
            appData.bluetoothManager.start()
27
            now = Date()
28
        }
29
        .onReceive(helpRefreshTimer) { currentDate in
30
            now = currentDate
31
        }
32
        .onChange(of: activeHelpAutoReason) { newReason in
33
            if newReason == nil {
34
                dismissedAutoHelpReason = nil
35
            }
36
        }
37
    }
38

            
39
    private var usbMetersSection: some View {
40
        SidebarUSBMetersSectionView(
41
            meters: appData.meterSummaries,
42
            managerState: appData.bluetoothManager.managerState,
43
            hasLiveMeters: appData.meters.isEmpty == false,
44
            scanStartedAt: appData.bluetoothManager.scanStartedAt,
45
            now: now,
46
            noDevicesHelpDelay: noDevicesHelpDelay
47
        )
48
    }
49

            
50
    private var helpSection: some View {
51
        SidebarHelpSectionView(
52
            activeReason: activeHelpAutoReason,
53
            isExpanded: helpIsExpanded,
54
            bluetoothStatusTint: appData.bluetoothManager.managerState.color,
55
            bluetoothStatusText: bluetoothStatusText,
56
            cloudSyncHelpTitle: appData.cloudAvailability.helpTitle,
57
            cloudSyncHelpMessage: appData.cloudAvailability.helpMessage,
58
            onToggle: toggleHelpSection,
59
            onOpenSettings: openSettings
60
        ) {
61
            appData.bluetoothManager.managerState.helpView
62
        } deviceHelpDestination: {
63
            DeviceHelpView()
64
        }
65
    }
66

            
67
    private var debugSection: some View {
68
        SidebarDebugSectionView()
69
    }
70

            
71
    private var bluetoothStatusText: String {
72
        switch appData.bluetoothManager.managerState {
73
        case .poweredOff:
74
            return "Off"
75
        case .poweredOn:
76
            return "On"
77
        case .resetting:
78
            return "Resetting"
79
        case .unauthorized:
80
            return "Unauthorized"
81
        case .unknown:
82
            return "Unknown"
83
        case .unsupported:
84
            return "Unsupported"
85
        @unknown default:
86
            return "Other"
87
        }
88
    }
89

            
90
    private var helpIsExpanded: Bool {
91
        isHelpExpanded || shouldAutoExpandHelp
92
    }
93

            
94
    private var shouldAutoExpandHelp: Bool {
95
        guard let activeHelpAutoReason else {
96
            return false
97
        }
98
        return dismissedAutoHelpReason != activeHelpAutoReason
99
    }
100

            
101
    private var activeHelpAutoReason: SidebarHelpReason? {
102
        SidebarAutoHelpResolver.activeReason(
103
            managerState: appData.bluetoothManager.managerState,
104
            cloudAvailability: appData.cloudAvailability,
105
            hasLiveMeters: appData.meters.isEmpty == false,
106
            scanStartedAt: appData.bluetoothManager.scanStartedAt,
107
            now: now,
108
            noDevicesHelpDelay: noDevicesHelpDelay
109
        )
110
    }
111

            
112
    private func toggleHelpSection() {
113
        withAnimation(.easeInOut(duration: 0.22)) {
114
            if shouldAutoExpandHelp {
115
                dismissedAutoHelpReason = activeHelpAutoReason
116
                isHelpExpanded = false
117
            } else {
118
                isHelpExpanded.toggle()
119
            }
120
        }
121
    }
122

            
123
    private func openSettings() {
124
        guard let settingsURL = URL(string: UIApplication.openSettingsURLString) else {
125
            return
126
        }
127
        UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil)
128
    }
129
}