burrow/Apple/UI/TunnelButton.swift
Conrad Kramer 85640ffce1
Some checks are pending
Build AppImage / Build AppImage (push) Waiting to run
Build Apple Apps / Build App (iOS) (push) Waiting to run
Build Apple Apps / Build App (iOS Simulator) (push) Waiting to run
Build Apple Apps / Build App (macOS) (push) Waiting to run
Build Docker / Build Docker Image (push) Waiting to run
Build Rust Crate / Build Crate (macOS (Intel)) (push) Waiting to run
Build Rust Crate / Build Crate (macOS) (push) Waiting to run
Build Rust Crate / Build Crate (Linux) (push) Waiting to run
Build Rust Crate / Build Crate (Windows) (push) Waiting to run
Switch to gRPC client in Swift app
2024-09-09 10:38:13 -07:00

73 lines
1.5 KiB
Swift

import SwiftUI
struct TunnelButton: View {
@Environment(\.tunnel)
var tunnel: any Tunnel
private var action: Action? { tunnel.action }
var body: some View {
Button {
if let action {
tunnel.perform(action)
}
} label: {
Text(action.description)
}
.disabled(action.isDisabled)
.padding(.horizontal)
.buttonStyle(.floating)
}
}
extension Tunnel {
@MainActor fileprivate var action: TunnelButton.Action? {
switch status {
case .permissionRequired, .invalid:
.enable
case .disabled, .disconnecting, .disconnected:
.start
case .connecting, .connected, .reasserting:
.stop
case .unknown, .configurationReadWriteFailed:
nil
}
}
}
extension TunnelButton {
fileprivate enum Action {
case enable
case start
case stop
}
}
extension TunnelButton.Action? {
var description: LocalizedStringKey {
switch self {
case .enable: "Enable"
case .start: "Start"
case .stop: "Stop"
case .none: "Start"
}
}
var isDisabled: Bool {
if case .none = self {
true
} else {
false
}
}
}
extension Tunnel {
fileprivate func perform(_ action: TunnelButton.Action) {
switch action {
case .enable: enable()
case .start: start()
case .stop: stop()
}
}
}