Files
ten31-transcripts/Ten31Transcripts/UI/PermissionRow.swift
T
Grant Gilliam b2ae3a62b9 Phase 0: menu-bar scaffold, permissions, backend health check
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)
2026-06-05 19:33:53 -05:00

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)
}
}
}
}