11// CertificateView.swift
22import SwiftUI
33import UniformTypeIdentifiers
4-
54// Centralized types to avoid conflicts
65struct CertificateFileItem {
76 var name : String = " "
87 var url : URL ?
98}
10-
119struct CustomCertificate : Identifiable {
1210 let id = UUID ( )
1311 let displayName : String
1412 let folderName : String
1513}
16-
1714// MARK: - CertificateView (List + Add/Edit launchers)
1815struct CertificateView : View {
1916 @State private var customCertificates : [ CustomCertificate ] = [ ]
@@ -22,7 +19,8 @@ struct CertificateView: View {
2219 @State private var selectedCert : String ? = nil
2320 @State private var showingDeleteAlert = false
2421 @State private var certToDelete : CustomCertificate ?
25-
22+ @State private var newlyAddedFolder : String ? = nil
23+
2624 var body : some View {
2725 // <-- Removed nested NavigationStack to avoid hiding the title from the parent stack
2826 ScrollView {
@@ -55,7 +53,7 @@ struct CertificateView: View {
5553 UserDefaults . standard. set ( selectedCert, forKey: " selectedCertificateFolder " )
5654 }
5755 }
58-
56+
5957 HStack {
6058 Button ( action: {
6159 // EDIT: trigger identifiable sheet
@@ -68,9 +66,9 @@ struct CertificateView: View {
6866 . background ( Color ( . systemGray6) . opacity ( 0.8 ) )
6967 . clipShape ( Circle ( ) )
7068 }
71-
69+
7270 Spacer ( )
73-
71+
7472 Button ( action: {
7573 if customCertificates. count > 1 {
7674 certToDelete = cert
@@ -106,8 +104,13 @@ struct CertificateView: View {
106104 // ADD sheet (new certificate only)
107105 . sheet ( isPresented: $showAddCertificateSheet, onDismiss: {
108106 reloadCertificatesAndEnsureSelection ( )
107+ if let newFolder = newlyAddedFolder {
108+ selectedCert = newFolder
109+ UserDefaults . standard. set ( selectedCert, forKey: " selectedCertificateFolder " )
110+ newlyAddedFolder = nil
111+ }
109112 } ) {
110- AddCertificateView ( )
113+ AddCertificateView ( onSave : { newlyAddedFolder = $0 } )
111114 . presentationDetents ( [ . large] )
112115 }
113116 // EDIT sheet (identifiable)
@@ -131,13 +134,13 @@ struct CertificateView: View {
131134 reloadCertificatesAndEnsureSelection ( )
132135 }
133136 }
134-
137+
135138 private func reloadCertificatesAndEnsureSelection( ) {
136139 customCertificates = CertificateFileManager . shared. loadCertificates ( )
137140 selectedCert = UserDefaults . standard. string ( forKey: " selectedCertificateFolder " )
138141 ensureSelection ( )
139142 }
140-
143+
141144 private func ensureSelection( ) {
142145 if selectedCert == nil || !customCertificates. contains ( where: { $0. folderName == selectedCert } ) {
143146 if let firstCert = customCertificates. first {
@@ -146,11 +149,11 @@ struct CertificateView: View {
146149 }
147150 }
148151 }
149-
152+
150153 private func deleteCertificate( _ cert: CustomCertificate ) {
151154 try ? CertificateFileManager . shared. deleteCertificate ( folderName: cert. folderName)
152155 customCertificates = CertificateFileManager . shared. loadCertificates ( )
153-
156+
154157 if selectedCert == cert. folderName {
155158 if let newSelection = customCertificates. first {
156159 selectedCert = newSelection. folderName
@@ -163,12 +166,12 @@ struct CertificateView: View {
163166 ensureSelection ( )
164167 }
165168}
166-
167169// MARK: - Add / Edit View
168170struct AddCertificateView : View {
169171 @Environment ( \. dismiss) private var dismiss
170172 let editingCertificate : CustomCertificate ?
171-
173+ let onSave : ( ( String ) -> Void ) ?
174+
172175 @State private var p12File : CertificateFileItem ?
173176 @State private var provFile : CertificateFileItem ?
174177 @State private var password = " "
@@ -177,11 +180,12 @@ struct AddCertificateView: View {
177180 @State private var errorMessage = " "
178181 @State private var displayName : String = " "
179182 @State private var hasLoadedForEdit = false
180-
181- init ( editingCertificate: CustomCertificate ? = nil ) {
183+
184+ init ( editingCertificate: CustomCertificate ? = nil , onSave : ( ( String ) -> Void ) ? = nil ) {
182185 self . editingCertificate = editingCertificate
186+ self . onSave = onSave
183187 }
184-
188+
185189 var body : some View {
186190 // Use a NavigationStack inside the sheet so the sheet has its own nav bar
187191 NavigationStack {
@@ -201,7 +205,7 @@ struct AddCertificateView: View {
201205 }
202206 }
203207 . disabled ( isChecking)
204-
208+
205209 Button ( action: { activeSheet = . prov } ) {
206210 HStack {
207211 Image ( systemName: " gearshape.fill " )
@@ -217,20 +221,20 @@ struct AddCertificateView: View {
217221 }
218222 . disabled ( isChecking)
219223 }
220-
224+
221225 Section ( header: Text ( " Display Name " ) ) {
222226 TextField ( " Optional Display Name " , text: $displayName)
223227 . disabled ( isChecking)
224228 }
225-
229+
226230 Section ( header: Text ( " Password " ) ) {
227231 SecureField ( " Enter Password " , text: $password)
228232 . disabled ( isChecking)
229233 Text ( " Enter the password for the certificate. Leave it blank if there is no password needed. " )
230234 . font ( . caption)
231235 . foregroundColor ( . secondary)
232236 }
233-
237+
234238 if !errorMessage. isEmpty {
235239 Text ( errorMessage)
236240 . foregroundColor ( . red)
@@ -246,7 +250,7 @@ struct AddCertificateView: View {
246250 }
247251 . disabled ( isChecking)
248252 }
249-
253+
250254 ToolbarItem ( placement: . navigationBarTrailing) {
251255 if isChecking {
252256 ProgressView ( )
@@ -279,17 +283,17 @@ struct AddCertificateView: View {
279283 }
280284 } // NavigationStack
281285 }
282-
286+
283287 private func loadForEdit( cert: CustomCertificate ) {
284288 let certFolder = CertificateFileManager . shared. certificatesDirectory. appendingPathComponent ( cert. folderName)
285289 let p12URL = certFolder. appendingPathComponent ( " certificate.p12 " )
286290 let provURL = certFolder. appendingPathComponent ( " profile.mobileprovision " )
287291 let passwordURL = certFolder. appendingPathComponent ( " password.txt " )
288292 let nameURL = certFolder. appendingPathComponent ( " name.txt " )
289-
293+
290294 p12File = CertificateFileItem ( name: " certificate.p12 " , url: p12URL)
291295 provFile = CertificateFileItem ( name: " profile.mobileprovision " , url: provURL)
292-
296+
293297 if let pwData = try ? Data ( contentsOf: passwordURL) , let pw = String ( data: pwData, encoding: . utf8) {
294298 password = pw
295299 }
@@ -299,10 +303,10 @@ struct AddCertificateView: View {
299303 }
300304 private func saveCertificate( ) {
301305 guard let p12URL = p12File? . url, let provURL = provFile? . url else { return }
302-
306+
303307 isChecking = true
304308 errorMessage = " "
305-
309+
306310 let workItem : DispatchWorkItem = DispatchWorkItem {
307311 do {
308312 var p12Data : Data
@@ -322,21 +326,22 @@ struct AddCertificateView: View {
322326 p12Data = try Data ( contentsOf: p12URL)
323327 provData = try Data ( contentsOf: provURL)
324328 }
325-
329+
326330 let checkResult = CertificatesManager . check ( p12Data: p12Data, password: self . password, mobileProvisionData: provData)
327331 var dispatchError : String ?
328-
332+
329333 switch checkResult {
330334 case . success( . success) :
331335 // Generate displayName from cert if not set
332336 if localDisplayName. isEmpty {
333337 localDisplayName = CertificatesManager . getCertificateName ( mobileProvisionData: provData) ?? " Custom Certificate "
334338 }
335-
339+
336340 if let folder = self . editingCertificate? . folderName {
337341 try CertificateFileManager . shared. updateCertificate ( folderName: folder, p12Data: p12Data, provData: provData, password: self . password, displayName: localDisplayName)
338342 } else {
339- _ = try CertificateFileManager . shared. saveCertificate ( p12Data: p12Data, provData: provData, password: self . password, displayName: localDisplayName)
343+ let newFolder = try CertificateFileManager . shared. saveCertificate ( p12Data: p12Data, provData: provData, password: self . password, displayName: localDisplayName)
344+ self . onSave ? ( newFolder)
340345 }
341346 case . success( . incorrectPassword) :
342347 dispatchError = " Incorrect Password "
@@ -345,7 +350,7 @@ struct AddCertificateView: View {
345350 case . failure( let error) :
346351 dispatchError = " Error: \( error. localizedDescription) "
347352 }
348-
353+
349354 DispatchQueue . main. async {
350355 self . isChecking = false
351356 if let err = dispatchError {
0 commit comments