@@ -100,7 +100,8 @@ class CertificateFileManager {
100100 try p12Data. write ( to: folderURL. appendingPathComponent ( " certificate.p12 " ) )
101101 try provData. write ( to: folderURL. appendingPathComponent ( " profile.mobileprovision " ) )
102102 try password. data ( using: . utf8) ? . write ( to: folderURL. appendingPathComponent ( " password.txt " ) )
103- try displayName. data ( using: . utf8) ? . write ( to: folderURL. appendingPathComponent ( " name.txt " ) )
103+ let displayToWrite = uniqueDisplayName ( displayName, excludingFolder: nil )
104+ try displayToWrite. data ( using: . utf8) ? . write ( to: folderURL. appendingPathComponent ( " name.txt " ) )
104105
105106 return finalName
106107 }
@@ -142,7 +143,8 @@ class CertificateFileManager {
142143 try p12Data. write ( to: certificateFolder. appendingPathComponent ( " certificate.p12 " ) )
143144 try provData. write ( to: certificateFolder. appendingPathComponent ( " profile.mobileprovision " ) )
144145 try password. data ( using: . utf8) ? . write ( to: certificateFolder. appendingPathComponent ( " password.txt " ) )
145- try displayName. data ( using: . utf8) ? . write ( to: certificateFolder. appendingPathComponent ( " name.txt " ) )
146+ let displayToWrite = uniqueDisplayName ( displayName, excludingFolder: folderName)
147+ try displayToWrite. data ( using: . utf8) ? . write ( to: certificateFolder. appendingPathComponent ( " name.txt " ) )
146148 }
147149
148150 func deleteCertificate( folderName: String ) throws {
@@ -154,6 +156,35 @@ class CertificateFileManager {
154156 let invalidChars = CharacterSet ( charactersIn: " :/ \\ ?%*| \" <> " )
155157 return name. components ( separatedBy: invalidChars) . joined ( separator: " _ " )
156158 }
159+
160+ // Return a unique display name by appending " 2", " 3", ... if needed.
161+ // `excludingFolder` lets updateCertificate keep the current folder's name out of the conflict check.
162+ private func uniqueDisplayName( _ desired: String , excludingFolder: String ? = nil ) -> String {
163+ let base = desired. isEmpty ? " Custom Certificate " : desired
164+ var existingNames = Set < String > ( )
165+ if let folders = try ? fileManager. contentsOfDirectory ( at: certificatesDirectory, includingPropertiesForKeys: nil , options: [ . skipsHiddenFiles] ) {
166+ for folder in folders {
167+ if folder. lastPathComponent == excludingFolder { continue }
168+ let nameURL = folder. appendingPathComponent ( " name.txt " )
169+ if let data = try ? Data ( contentsOf: nameURL) , let s = String ( data: data, encoding: . utf8) {
170+ existingNames. insert ( s)
171+ } else {
172+ // fallback to folder name if name.txt missing
173+ existingNames. insert ( folder. lastPathComponent)
174+ }
175+ }
176+ }
177+
178+ if !existingNames. contains ( base) {
179+ return base
180+ }
181+
182+ var counter = 2
183+ while existingNames. contains ( " \( base) \( counter) " ) {
184+ counter += 1
185+ }
186+ return " \( base) \( counter) "
187+ }
157188}
158189
159190// MARK: - CertificateView (List + Add/Edit launchers)
@@ -440,7 +471,7 @@ struct AddCertificateView: View {
440471 displayName = nameStr
441472 }
442473 }
443-
474+
444475 private func saveCertificate( ) {
445476 guard let p12URL = p12File? . url, let provURL = provFile? . url else { return }
446477
0 commit comments