// // PersonalDataApprovalSheet.swift // oAI // // Approval UI for AI-requested Calendar/Reminders write actions // // SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0 // Copyright (C) 2026 Rune Olsen // // This file is part of oAI. // // oAI is licensed under the PolyForm Noncommercial License 1.0.0. // You may use, study, modify, and share it for any noncommercial // purpose. Commercial use — including selling oAI or any part of // it, standalone or bundled into another product or service — // requires a separate commercial license from the copyright holder. // // See the LICENSE file or // for // the full license text. For commercial licensing, contact Rune // Olsen via . import SwiftUI struct PersonalDataApprovalSheet: View { let pending: MCPService.PendingPersonalDataAction let onApprove: (_ forSession: Bool) -> Void let onDeny: () -> Void var body: some View { VStack(alignment: .leading, spacing: 20) { // Header HStack(spacing: 12) { Image(systemName: "calendar.badge.exclamationmark") .font(.title2) .foregroundStyle(.orange) VStack(alignment: .leading, spacing: 2) { Text("Allow This Action?") .font(.system(size: 17, weight: .semibold)) Text("The AI wants to make a change to your calendar or reminders") .font(.system(size: 13)) .foregroundStyle(.secondary) } Spacer() } // Action description VStack(alignment: .leading, spacing: 6) { Text("ACTION") .font(.system(size: 11, weight: .medium)) .foregroundStyle(.secondary) Text(pending.summary) .font(.system(size: 13)) .foregroundStyle(.primary) .frame(maxWidth: .infinity, alignment: .leading) .textSelection(.enabled) .padding(12) .background(Color.secondary.opacity(0.08)) .clipShape(RoundedRectangle(cornerRadius: 8)) .overlay( RoundedRectangle(cornerRadius: 8) .stroke(Color.secondary.opacity(0.2), lineWidth: 1) ) } // Buttons HStack(spacing: 8) { Button("Deny") { onDeny() } .buttonStyle(.bordered) .tint(.red) .keyboardShortcut(.escape, modifiers: []) Spacer() Button("Allow Once") { onApprove(false) } .buttonStyle(.bordered) .tint(.orange) Button("Allow for Session") { onApprove(true) } .buttonStyle(.borderedProminent) .tint(.orange) .keyboardShortcut(.return, modifiers: []) } } .padding(24) .frame(width: 480) } }