import SwiftUI struct MenuBarView: View { @Environment(TTLManager.self) private var ttlManager @Environment(\.openWindow) private var openWindow @Environment(\.colorScheme) private var colorScheme @State private var isProcessing = false @State private var showError = false @State private var errorMessage = "" private let authService = AuthenticationService() private let commandService = SystemCommandService() private var accentColor: Color { if colorScheme == .light { return ttlManager.isProtected ? Color(hue: 0.38, saturation: 0.85, brightness: 0.40) : Color(hue: 0.05, saturation: 0.90, brightness: 0.45) } else { return ttlManager.isProtected ? Color(hue: 0.38, saturation: 0.70, brightness: 0.85) : Color(hue: 0.06, saturation: 0.70, brightness: 0.90) } } var body: some View { VStack(spacing: 14) { // Header HStack(spacing: 10) { Image(systemName: ttlManager.isProtected ? "antenna.radiowaves.left.and.right" : "antenna.radiowaves.left.and.right.slash") .font(.system(size: 20, weight: .medium)) .foregroundStyle(accentColor) .symbolEffect(.bounce, value: ttlManager.isProtected) VStack(alignment: .leading, spacing: 2) { Text("Tethering Hider") .font(.system(size: 13, weight: .bold, design: .rounded)) Text(ttlManager.isProtected ? "Protected (TTL 65)" : "Exposed (TTL 64)") .font(.system(size: 11, weight: .medium)) .foregroundStyle(accentColor) } Spacer() // Toggle Switch Toggle("", isOn: Binding( get: { ttlManager.isProtected }, set: { newValue in if newValue { activateProtection() } else { deactivateProtection() } } )) .toggleStyle(.switch) .disabled(isProcessing) .tint(accentColor) } .padding(.horizontal, 14) .padding(.vertical, 10) .background( RoundedRectangle(cornerRadius: 12) .fill(.ultraThinMaterial) .overlay( RoundedRectangle(cornerRadius: 12) .stroke(accentColor.opacity(0.2), lineWidth: 0.5) ) ) .modifier(GlassCardModifier(tintColor: accentColor)) // Status Badges HStack(spacing: 6) { badgeItem(title: "IPv4", val: "\(ttlManager.currentTTL)", active: ttlManager.currentTTL == 65) badgeItem(title: "IPv6", val: "\(ttlManager.currentIPv6HopLimit)", active: ttlManager.currentIPv6HopLimit == 65) badgeItem(title: "DNS", val: "FLUSH", active: ttlManager.isProtected) } Divider() .opacity(0.3) // Action Links VStack(spacing: 6) { Button { NSApp.activate(ignoringOtherApps: true) openWindow(id: "mainWindow") } label: { Label("Open Dashboard", systemImage: "macwindow") .font(.system(size: 12, weight: .medium)) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) } .buttonStyle(.plain) .padding(.horizontal, 10) .padding(.vertical, 6) .background(RoundedRectangle(cornerRadius: 6).fill(Color.primary.opacity(0.05))) Button(role: .destructive) { NSApp.terminate(nil) } label: { Label("Quit Tethering Hider", systemImage: "power") .font(.system(size: 12, weight: .medium)) .foregroundStyle(.red) .frame(maxWidth: .infinity, alignment: .leading) .contentShape(Rectangle()) } .buttonStyle(.plain) .padding(.horizontal, 10) .padding(.vertical, 6) } } .padding(14) .frame(width: 280) .alert("Error", isPresented: $showError) { Button("OK", role: .cancel) { } } message: { Text(errorMessage) } .task { ttlManager.refreshStatus() } } private func badgeItem(title: String, val: String, active: Bool) -> some View { HStack(spacing: 3) { Circle() .fill(active ? Color.green : Color.orange) .frame(width: 4, height: 4) Text("\(title): \(val)") .font(.system(size: 9, weight: .medium, design: .monospaced)) .foregroundStyle(.secondary) } .padding(.horizontal, 6) .padding(.vertical, 3) .background(Capsule().fill(.ultraThinMaterial)) } private func activateProtection() { Task { isProcessing = true defer { isProcessing = false } do { let authenticated = try await authService.authenticateWithBiometrics() guard authenticated else { return } try await commandService.setTTL(ttlManager.targetTTL) ttlManager.didSetTTL(ttlManager.targetTTL) } catch is AuthenticationError { } catch SystemCommandError.userCancelledAuth { } catch { errorMessage = error.localizedDescription showError = true ttlManager.setError(error.localizedDescription) } } } private func deactivateProtection() { Task { isProcessing = true defer { isProcessing = false } do { let authenticated = try await authService.authenticateWithBiometrics() guard authenticated else { return } try await commandService.resetTTL() ttlManager.didSetTTL(ttlManager.defaultTTL) } catch is AuthenticationError { } catch SystemCommandError.userCancelledAuth { } catch { errorMessage = error.localizedDescription showError = true ttlManager.setError(error.localizedDescription) } } } }