import SwiftUI import AppKit struct EnrollView: View { @Environment(WizardModel.self) private var model @State private var downloadStatus: String? @State private var localPath: String? var body: some View { VStack(alignment: .leading, spacing: 20) { header Text("Jetzt installierst du das **minimale** MDM-Enrollment-Profile, damit dein iPhone mit unserem NanoMDM-Server (mdm.rebreak.org) sprechen kann. Das Profile bringt **keine Restrictions** — nur den MDM-Channel. Restrictions kommen später per Sideload-Lock.") .foregroundStyle(.secondary) instructions Spacer() navigationBar } .padding(40) .onAppear { downloadProfile() } } private var header: some View { HStack { Image(systemName: "doc.badge.gearshape") .font(.system(size: 30)) .foregroundStyle(.tint) Text("MDM-Enrollment") .font(.title).bold() } } private var instructions: some View { VStack(alignment: .leading, spacing: 14) { stepRow(number: 1, text: "Profile wird automatisch vom Server runtergeladen.") if let status = downloadStatus { HStack(spacing: 8) { Image(systemName: localPath != nil ? "checkmark.circle.fill" : "arrow.down.circle") .foregroundStyle(localPath != nil ? .green : .secondary) Text(status).font(.caption).foregroundStyle(.secondary) } .padding(.leading, 36) } stepRow(number: 2, text: "Klick „Per AirDrop senden\" → wähle dein iPhone im Sheet.") stepRow(number: 3, text: "Am iPhone: AirDrop-Dialog akzeptieren → Settings öffnet sich automatisch.") stepRow(number: 4, text: "Settings → „Installieren\" tappen → 6-stelligen Geräte-Code eingeben → „Installieren\" bestätigen.") stepRow(number: 5, text: "Zurück hier klick auf „Enrollment fertig → Weiter\".") } } private func stepRow(number: Int, text: String) -> some View { HStack(alignment: .top, spacing: 12) { ZStack { Circle().fill(Color.accentColor) Text("\(number)").foregroundStyle(.white).bold() } .frame(width: 24, height: 24) Text(text) .fixedSize(horizontal: false, vertical: true) Spacer() } } private var navigationBar: some View { HStack { Button("Zurück") { model.goTo(.supervise) } .buttonStyle(.bordered) Spacer() if let path = localPath { Button("Per AirDrop senden") { sendViaAirDrop(path: path) } .buttonStyle(.borderedProminent) Button("…im Finder zeigen") { NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: path)]) } .buttonStyle(.bordered) } Button("Enrollment fertig → Weiter") { model.device?.isEnrolled = true model.advance() } .buttonStyle(.bordered) } } private func downloadProfile() { let dest = "/tmp/rebreak-enrollment.mobileconfig" downloadStatus = "Lade von mdm.rebreak.org …" Task { do { guard let url = URL(string: "https://mdm.rebreak.org/enrollment/rebreak-enrollment.mobileconfig") else { throw URLError(.badURL) } let (data, response) = try await URLSession.shared.data(from: url) guard let http = response as? HTTPURLResponse, http.statusCode == 200 else { throw URLError(.badServerResponse) } try data.write(to: URL(fileURLWithPath: dest)) await MainActor.run { localPath = dest downloadStatus = "Geladen: \(dest) (\(data.count) Bytes)" } } catch { await MainActor.run { downloadStatus = "Download fehlgeschlagen: \(error.localizedDescription)" } } } } private func sendViaAirDrop(path: String) { let url = URL(fileURLWithPath: path) guard let service = NSSharingService(named: .sendViaAirDrop), service.canPerform(withItems: [url]) else { NSWorkspace.shared.activateFileViewerSelecting([url]) return } service.perform(withItems: [url]) } }