// // TriStateToggle.swift // Tusker // // Created by Shadowfacts on 4/7/24. // Copyright © 2024 Shadowfacts. All rights reserved. // import SwiftUI struct TriStateToggle: View { let titleKey: LocalizedStringKey @Binding var mode: Mode let onChange: (Bool) async -> Void @State private var isOn: Bool init(titleKey: LocalizedStringKey, mode: Binding, onChange: @escaping (Bool) async -> Void) { self.titleKey = titleKey self._mode = mode self.onChange = onChange self.isOn = mode.wrappedValue == .on } var body: some View { toggleOrSpinner .onChange(of: mode) { newValue in switch newValue { case .off: isOn = false case .loading: break case .on: isOn = true } } } @ViewBuilder private var toggleOrSpinner: some View { if mode == .loading { ProgressView() } else { Toggle(titleKey, isOn: Binding { isOn } set: { newValue in isOn = newValue mode = .loading Task { await onChange(newValue) mode = newValue ? .on : .off } }) .labelsHidden() } } enum Mode { case off case loading case on } } #Preview { @State var mode = TriStateToggle.Mode.on return TriStateToggle(titleKey: "", mode: $mode) { _ in try! await Task.sleep(nanoseconds: NSEC_PER_SEC) } }