import SwiftUI import SFSafeSymbols struct ContentView: View { @Environment(\.colorScheme) var defaultColorScheme: ColorScheme let info: CVInfo let style: CVStyle init(info: CVInfo, style: CVStyle) { self.info = info self.style = style } @State var darkModeEnabled = true @State var didReadDarkMode = false var colorStyle: ColorScheme { darkModeEnabled ? .dark : .light } var body: some View { VStack(alignment: .leading) { HStack { Button(action: createAndSavePDF) { Label("Save", systemSymbol: .squareAndArrowUp) } .padding() Toggle("Dark mode", isOn: $darkModeEnabled) } ScrollView(.vertical) { CV(info: info, style: style) }.frame(width: style.pageWidth) } .preferredColorScheme(colorStyle) .onAppear { guard !didReadDarkMode else { return } darkModeEnabled = defaultColorScheme == .dark didReadDarkMode = true } } private func createAndSavePDF() { DispatchQueue.main.async { guard let pdfURL = renderPDF() else { return } guard let url = showSavePanel() else { return } writePDF(at: pdfURL, to: url) } } private func showSavePanel() -> URL? { let savePanel = NSSavePanel() savePanel.allowedContentTypes = [.pdf] savePanel.canCreateDirectories = true savePanel.isExtensionHidden = false savePanel.allowsOtherFileTypes = false savePanel.title = "Save PDF" savePanel.message = "Choose a location to save a PDF of the resume" savePanel.nameFieldLabel = "File name:" savePanel.nameFieldStringValue = "CV.pdf" let response = savePanel.runModal() guard response == .OK else { return nil } return savePanel.url } private func writePDF(at source: URL, to destination: URL) { do { if FileManager.default.fileExists(atPath: destination.path) { try FileManager.default.removeItem(at: destination) } try FileManager.default.copyItem(at: source, to: destination) } catch { print("Failed to save pdf: \(error)") } } private var content: some View { CV(info: info, style: style) .frame(width: style.pageWidth, height: style.pageHeight) } @MainActor private func renderPDF() -> URL? { let pdfURL = URL.documentsDirectory.appending(path: "cv.pdf") let renderer = ImageRenderer(content: content) var didFinish = false renderer.render { size, context in var box = CGRect(x: 0, y: 0, width: size.width, height: size.height) guard let pdf = CGContext(pdfURL as CFURL, mediaBox: &box, nil) else { print("Failed to create CGContext") return } let options: [CFString: Any] = [ kCGPDFContextMediaBox: CGRect(origin: .zero, size: size) ] pdf.beginPDFPage(options as CFDictionary) context(pdf) pdf.endPDFPage() pdf.closePDF() didFinish = true } guard didFinish else { return nil } print("PDF created") return pdfURL } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView(info: cvInfo, style: cvStyle) .frame(width: 600, height: 600 * sqrt(2)) } }