b2ae3a62b9
Native SwiftUI menu-bar app (LSUIElement, macOS 13+), generated from project.yml via XcodeGen. Includes: - PermissionsManager (Microphone / Screen Recording / Accessibility) + UI - SparkControlHealth: GET /api/status over self-signed TLS (InsecureTrustDelegate) - AppSettings persistence (host, TLS-skip, output folder, adapter toggles) - Menu-bar panel + Settings, app sandbox & hardened runtime off (LAN tool)
55 lines
1.6 KiB
Swift
55 lines
1.6 KiB
Swift
import SwiftUI
|
|
|
|
/// Small status indicator dot.
|
|
struct StatusDot: View {
|
|
let color: Color
|
|
var body: some View {
|
|
Circle().fill(color).frame(width: 9, height: 9)
|
|
}
|
|
}
|
|
|
|
/// One permission line: status dot, label, and a context-appropriate action.
|
|
struct PermissionRow: View {
|
|
let title: String
|
|
let state: PermissionState
|
|
let onGrant: () -> Void
|
|
let onOpenSettings: () -> Void
|
|
|
|
var body: some View {
|
|
HStack(spacing: 8) {
|
|
StatusDot(color: dotColor)
|
|
Text(title)
|
|
Spacer()
|
|
actionButton
|
|
}
|
|
}
|
|
|
|
private var dotColor: Color {
|
|
switch state {
|
|
case .granted: return .green
|
|
case .denied: return .red
|
|
case .notDetermined: return .orange
|
|
}
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var actionButton: some View {
|
|
switch state {
|
|
case .granted:
|
|
Image(systemName: "checkmark.circle.fill").foregroundStyle(.green)
|
|
case .notDetermined:
|
|
// Native prompt (Microphone). The request also registers the app.
|
|
Button("Grant", action: onGrant)
|
|
case .denied:
|
|
// Screen Recording / Accessibility report binary granted/denied, so
|
|
// "not yet asked" looks like denied. "Grant" calls the request API,
|
|
// which registers the app in the relevant list and shows the system
|
|
// prompt the first time; "Open Settings" is the manual fallback.
|
|
HStack(spacing: 6) {
|
|
Button("Grant", action: onGrant)
|
|
Button("Open Settings", action: onOpenSettings)
|
|
}
|
|
}
|
|
}
|
|
}
|