Skip to content
This repository was archived by the owner on Mar 7, 2026. It is now read-only.

Commit b655bda

Browse files
authored
Remove SignerView
1 parent 089d27d commit b655bda

2 files changed

Lines changed: 0 additions & 292 deletions

File tree

Sources/prostore/prostore.swift

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ struct MainSidebarView: View {
1818
NavigationLink(value: SidebarItem.apps) {
1919
Label("Apps", systemImage: "square.grid.2x2.fill")
2020
}
21-
NavigationLink(value: SidebarItem.signer) {
22-
Label("Signer", systemImage: "hammer")
23-
}
2421
NavigationLink(value: SidebarItem.certificates) {
2522
Label("Certificates", systemImage: "key")
2623
}
@@ -34,12 +31,6 @@ struct MainSidebarView: View {
3431
.navigationTitle("ProStore")
3532
} detail: {
3633
switch selected {
37-
case .signer:
38-
NavigationStack {
39-
SignerView()
40-
.navigationTitle("Signer")
41-
.navigationBarTitleDisplayMode(.large)
42-
}
4334
case .certificates:
4435
NavigationStack {
4536
CertificateView()
@@ -82,7 +73,6 @@ struct MainSidebarView: View {
8273
}
8374

8475
enum SidebarItem: Hashable {
85-
case signer
8676
case updater
8777
case certificates
8878
case apps
Lines changed: 0 additions & 282 deletions
Original file line numberDiff line numberDiff line change
@@ -1,282 +0,0 @@
1-
import SwiftUI
2-
import UniformTypeIdentifiers
3-
4-
struct SignerView: View {
5-
@StateObject private var ipa = FileItem()
6-
@State private var isProcessing = false
7-
@State private var overallProgress: Double = 0.0
8-
@State private var currentStage: String = ""
9-
@State private var barColor: Color = .blue
10-
@State private var isError: Bool = false
11-
@State private var errorDetails: String = ""
12-
@State private var showActivity = false
13-
@State private var activityURL: URL? = nil
14-
@State private var showPickerFor: PickerKind? = nil
15-
@State private var selectedCertificateName: String? = nil
16-
@State private var expireStatus: String = "Unknown"
17-
@State private var hasSelectedCertificate: Bool = false
18-
19-
var body: some View {
20-
Form {
21-
Section(header: Text("Inputs")
22-
.font(.headline)
23-
.foregroundColor(.primary)
24-
.padding(.top, 8)) {
25-
// IPA picker with icon and truncated file name
26-
HStack {
27-
Image(systemName: "doc.fill")
28-
.foregroundColor(.blue)
29-
Text("IPA")
30-
Spacer()
31-
Text(ipa.name.isEmpty ? "No file selected selected" : ipa.name)
32-
.font(.caption)
33-
.lineLimit(1)
34-
.foregroundColor(.secondary)
35-
Button(action: {
36-
showPickerFor = .ipa
37-
}) {
38-
Text("Pick")
39-
.padding(.horizontal, 8)
40-
.padding(.vertical, 4)
41-
.background(Color.blue.opacity(0.1))
42-
.cornerRadius(8)
43-
}
44-
}
45-
.padding(.vertical, 4)
46-
if hasSelectedCertificate, let name = selectedCertificateName {
47-
Text("The \(name) certificate (\(expireStatus)) will be used to sign the ipa file. If you wish to use a different certificate for signing, please select or add it to the certificates page.")
48-
.font(.subheadline)
49-
.foregroundColor(.secondary)
50-
.padding(.vertical, 4)
51-
} else {
52-
Text("No certificate selected. Please add and select one in the Certificates tab.")
53-
.foregroundColor(.red)
54-
.padding(.vertical, 4)
55-
}
56-
}
57-
Section {
58-
Button(action: runSign) {
59-
HStack {
60-
Spacer()
61-
Text("Sign IPA")
62-
.font(.headline)
63-
.foregroundColor(.white)
64-
.padding()
65-
.frame(maxWidth: .infinity)
66-
.background(isProcessing || ipa.url == nil || !hasSelectedCertificate ? Color.gray : Color.blue)
67-
.cornerRadius(10)
68-
.shadow(radius: 2)
69-
Spacer()
70-
}
71-
}
72-
.disabled(isProcessing || ipa.url == nil || !hasSelectedCertificate)
73-
.scaleEffect(isProcessing ? 0.95 : 1.0)
74-
.animation(.easeInOut(duration: 0.2), value: isProcessing)
75-
}
76-
.padding(.vertical, 8)
77-
if isProcessing || !currentStage.isEmpty {
78-
Section(header: Text("Progress")
79-
.font(.headline)
80-
.foregroundColor(.primary)
81-
.padding(.top, 8)) {
82-
HStack {
83-
Text(currentStage)
84-
.foregroundColor(currentStage == "Error" ? .red : currentStage == "Done!" ? .green : .primary)
85-
.animation(.easeInOut(duration: 0.2), value: currentStage)
86-
ProgressView(value: overallProgress)
87-
.progressViewStyle(.linear)
88-
.tint(barColor)
89-
.frame(maxWidth: .infinity)
90-
.animation(.easeInOut(duration: 0.5), value: overallProgress)
91-
.animation(.default, value: barColor)
92-
Text("\(Int(overallProgress * 100))%")
93-
.foregroundColor(currentStage == "Error" ? .red : currentStage == "Done!" ? .green : .primary)
94-
.animation(nil, value: overallProgress)
95-
}
96-
if isError {
97-
Text(errorDetails)
98-
.foregroundColor(.red)
99-
.font(.subheadline)
100-
}
101-
}
102-
}
103-
}
104-
.accentColor(.blue)
105-
.sheet(item: $showPickerFor, onDismiss: nil) { kind in
106-
DocumentPicker(kind: kind, onPick: { url in
107-
switch kind {
108-
case .ipa:
109-
ipa.url = url
110-
default:
111-
break
112-
}
113-
})
114-
}
115-
.sheet(isPresented: $showActivity) {
116-
if let u = activityURL {
117-
ActivityView(url: u)
118-
} else {
119-
Text("No file to share")
120-
.foregroundColor(.red)
121-
}
122-
}
123-
.onAppear {
124-
loadSelectedCertificate()
125-
}
126-
}
127-
128-
private func loadSelectedCertificate() {
129-
guard let selectedFolder = UserDefaults.standard.string(forKey: "selectedCertificateFolder") else {
130-
hasSelectedCertificate = false
131-
return
132-
}
133-
let certDir = CertificateFileManager.shared.certificatesDirectory.appendingPathComponent(selectedFolder)
134-
if let nameData = try? Data(contentsOf: certDir.appendingPathComponent("name.txt")),
135-
let name = String(data: nameData, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines),
136-
!name.isEmpty {
137-
selectedCertificateName = name
138-
} else {
139-
selectedCertificateName = "Custom Certificate"
140-
}
141-
let provURL = certDir.appendingPathComponent("profile.mobileprovision")
142-
if let expiry = signer.getExpirationDate(provURL: provURL) {
143-
let now = Date()
144-
let components = Calendar.current.dateComponents([.day], from: now, to: expiry)
145-
let days = components.day ?? 0
146-
switch days {
147-
case ..<0, 0:
148-
expireStatus = "Expired"
149-
case 1...30:
150-
expireStatus = "Expiring Soon"
151-
default:
152-
expireStatus = "Valid"
153-
}
154-
} else {
155-
expireStatus = "Unknown"
156-
}
157-
hasSelectedCertificate = true
158-
}
159-
160-
func runSign() {
161-
guard let ipaURL = ipa.url else {
162-
currentStage = "Error"
163-
errorDetails = "Pick IPA file first 😅"
164-
isError = true
165-
withAnimation {
166-
overallProgress = 1.0
167-
barColor = .red
168-
}
169-
return
170-
}
171-
guard let selectedFolder = UserDefaults.standard.string(forKey: "selectedCertificateFolder") else {
172-
currentStage = "Error"
173-
errorDetails = "No certificate selected 😅"
174-
isError = true
175-
withAnimation {
176-
overallProgress = 1.0
177-
barColor = .red
178-
}
179-
return
180-
}
181-
let certDir = CertificateFileManager.shared.certificatesDirectory.appendingPathComponent(selectedFolder)
182-
let p12URL = certDir.appendingPathComponent("certificate.p12")
183-
let provURL = certDir.appendingPathComponent("profile.mobileprovision")
184-
let passwordURL = certDir.appendingPathComponent("password.txt")
185-
guard FileManager.default.fileExists(atPath: p12URL.path), FileManager.default.fileExists(atPath: provURL.path) else {
186-
currentStage = "Error"
187-
errorDetails = "Error loading certificate files 😅"
188-
isError = true
189-
withAnimation {
190-
overallProgress = 1.0
191-
barColor = .red
192-
}
193-
return
194-
}
195-
let p12Password: String
196-
if let passwordData = try? Data(contentsOf: passwordURL),
197-
let passwordStr = String(data: passwordData, encoding: .utf8) {
198-
p12Password = passwordStr
199-
} else {
200-
p12Password = ""
201-
}
202-
isProcessing = true
203-
currentStage = "Preparing"
204-
overallProgress = 0.0
205-
barColor = .blue
206-
isError = false
207-
errorDetails = ""
208-
signer.sign(
209-
ipaURL: ipaURL,
210-
p12URL: p12URL,
211-
provURL: provURL,
212-
p12Password: p12Password,
213-
progressUpdate: { message in
214-
DispatchQueue.main.async {
215-
updateProgress(from: message)
216-
}
217-
},
218-
completion: { result in
219-
DispatchQueue.main.async {
220-
isProcessing = false
221-
switch result {
222-
case .success(let signedIPAURL):
223-
activityURL = signedIPAURL
224-
withAnimation {
225-
overallProgress = 1.0
226-
barColor = .green
227-
currentStage = "Done!"
228-
}
229-
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
230-
showActivity = true
231-
}
232-
case .failure(let error):
233-
withAnimation {
234-
overallProgress = 1.0
235-
barColor = .red
236-
currentStage = "Error"
237-
}
238-
isError = true
239-
errorDetails = error.localizedDescription
240-
}
241-
}
242-
}
243-
)
244-
}
245-
246-
private func updateProgress(from message: String) {
247-
if message.contains("Preparing") {
248-
currentStage = "Preparing"
249-
overallProgress = 0.0
250-
} else if message.contains("Unzipping") {
251-
currentStage = "Unzipping"
252-
if let pct = extractPercentage(from: message) {
253-
overallProgress = 0.25 + (pct / 100.0) * 0.25
254-
} else {
255-
overallProgress = 0.25
256-
}
257-
} else if message.contains("Signing") {
258-
currentStage = "Signing"
259-
overallProgress = 0.5
260-
} else if message.contains("Zipping") {
261-
currentStage = "Zipping"
262-
if let pct = extractPercentage(from: message) {
263-
overallProgress = 0.75 + (pct / 100.0) * 0.25
264-
} else {
265-
overallProgress = 0.75
266-
}
267-
}
268-
}
269-
270-
private func extractPercentage(from message: String) -> Double? {
271-
if let range = message.range(of: "(") {
272-
let substring = message[range.lowerBound...]
273-
if let endRange = substring.range(of: "%)") {
274-
let pctString = substring[..<endRange.lowerBound].dropFirst()
275-
return Double(pctString)
276-
}
277-
}
278-
return nil
279-
}
280-
281-
}
282-

0 commit comments

Comments
 (0)