112 lines
3.7 KiB
Swift
112 lines
3.7 KiB
Swift
import SwiftUI
|
|
|
|
struct RootTabs: View {
|
|
@EnvironmentObject private var appModel: NodeAppModel
|
|
@State private var isConnectingPulse: Bool = false
|
|
|
|
var body: some View {
|
|
TabView {
|
|
ScreenTab()
|
|
.tabItem { Label("Screen", systemImage: "rectangle.and.hand.point.up.left") }
|
|
|
|
VoiceTab()
|
|
.tabItem { Label("Voice", systemImage: "mic") }
|
|
|
|
SettingsTab()
|
|
.tabItem {
|
|
VStack {
|
|
ZStack(alignment: .topTrailing) {
|
|
Image(systemName: "gearshape")
|
|
Circle()
|
|
.fill(self.settingsIndicatorColor)
|
|
.frame(width: 9, height: 9)
|
|
.overlay(
|
|
Circle()
|
|
.stroke(.black.opacity(0.2), lineWidth: 0.5))
|
|
.shadow(
|
|
color: self.settingsIndicatorGlowColor,
|
|
radius: self.settingsIndicatorGlowRadius,
|
|
x: 0,
|
|
y: 0)
|
|
.scaleEffect(self.settingsIndicatorScale)
|
|
.opacity(self.settingsIndicatorOpacity)
|
|
.offset(x: 7, y: -2)
|
|
}
|
|
Text("Settings")
|
|
}
|
|
}
|
|
}
|
|
.onAppear { self.updateConnectingPulse(for: self.bridgeIndicatorState) }
|
|
.onChange(of: self.bridgeIndicatorState) { _, newValue in
|
|
self.updateConnectingPulse(for: newValue)
|
|
}
|
|
}
|
|
|
|
private enum BridgeIndicatorState {
|
|
case connected
|
|
case connecting
|
|
case disconnected
|
|
}
|
|
|
|
private var bridgeIndicatorState: BridgeIndicatorState {
|
|
if self.appModel.bridgeServerName != nil { return .connected }
|
|
if self.appModel.bridgeStatusText.localizedCaseInsensitiveContains("connecting") { return .connecting }
|
|
return .disconnected
|
|
}
|
|
|
|
private var settingsIndicatorColor: Color {
|
|
switch self.bridgeIndicatorState {
|
|
case .connected:
|
|
Color.green
|
|
case .connecting:
|
|
Color.yellow
|
|
case .disconnected:
|
|
Color.red
|
|
}
|
|
}
|
|
|
|
private var settingsIndicatorGlowColor: Color {
|
|
switch self.bridgeIndicatorState {
|
|
case .connected:
|
|
Color.green.opacity(0.75)
|
|
case .connecting:
|
|
Color.yellow.opacity(0.6)
|
|
case .disconnected:
|
|
Color.clear
|
|
}
|
|
}
|
|
|
|
private var settingsIndicatorGlowRadius: CGFloat {
|
|
switch self.bridgeIndicatorState {
|
|
case .connected:
|
|
6
|
|
case .connecting:
|
|
self.isConnectingPulse ? 6 : 3
|
|
case .disconnected:
|
|
0
|
|
}
|
|
}
|
|
|
|
private var settingsIndicatorScale: CGFloat {
|
|
guard self.bridgeIndicatorState == .connecting else { return 1 }
|
|
return self.isConnectingPulse ? 1.12 : 0.96
|
|
}
|
|
|
|
private var settingsIndicatorOpacity: Double {
|
|
guard self.bridgeIndicatorState == .connecting else { return 1 }
|
|
return self.isConnectingPulse ? 1.0 : 0.75
|
|
}
|
|
|
|
private func updateConnectingPulse(for state: BridgeIndicatorState) {
|
|
guard state == .connecting else {
|
|
withAnimation(.easeOut(duration: 0.2)) { self.isConnectingPulse = false }
|
|
return
|
|
}
|
|
|
|
guard !self.isConnectingPulse else { return }
|
|
withAnimation(.easeInOut(duration: 0.9).repeatForever(autoreverses: true)) {
|
|
self.isConnectingPulse = true
|
|
}
|
|
}
|
|
}
|