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

Commit ac24be3

Browse files
authored
Update SetupView
1 parent 4ff40bd commit ac24be3

2 files changed

Lines changed: 24 additions & 163 deletions

File tree

Lines changed: 22 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -1,116 +1,28 @@
11
import SwiftUI
22
import UIKit
3-
import GCDWebServer
4-
5-
// MARK: - Cert server manager
6-
final class CertServerManager: ObservableObject {
7-
private var webServer: GCDWebServer?
8-
private var didServeOnce = false
9-
10-
/// Start a web server that serves certURL at path /ProStore.crt, open the URL in Safari
11-
func serveAndOpen(certURL: URL) -> Bool {
12-
stopServer()
13-
didServeOnce = false
14-
15-
let server = GCDWebServer()
16-
self.webServer = server
17-
18-
server.addHandler(
19-
forMethod: "GET",
20-
path: "/ProStore.crt",
21-
request: GCDWebServerRequest.self,
22-
processBlock: { [weak self] request in
23-
do {
24-
let data = try Data(contentsOf: certURL)
25-
let response = GCDWebServerDataResponse(data: data, contentType: "application/x-x509-ca-cert")
26-
response.setValue("attachment; filename=\"ProStore.crt\"", forAdditionalHeader: "Content-Disposition")
27-
28-
DispatchQueue.main.async {
29-
guard let self = self else { return }
30-
if !self.didServeOnce {
31-
self.didServeOnce = true
32-
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
33-
self.stopServer()
34-
}
35-
}
36-
}
37-
38-
return response
39-
} catch {
40-
return GCDWebServerResponse(statusCode: 500)
41-
}
42-
}
43-
)
44-
45-
let started = server.start(withPort: 0, bonjourName: nil)
46-
guard started, let serverURL = server.serverURL else {
47-
print("[CertServerManager] Failed to start web server")
48-
self.webServer = nil
49-
return false
50-
}
51-
52-
let openURL = serverURL.appendingPathComponent("ProStore.crt")
53-
DispatchQueue.main.async {
54-
UIApplication.shared.open(openURL, options: [:]) { success in
55-
if !success {
56-
print("[CertServerManager] Failed to open URL: \(openURL)")
57-
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
58-
self.stopServer()
59-
}
60-
} else {
61-
print("[CertServerManager] Opened URL: \(openURL)")
62-
}
63-
}
64-
}
65-
66-
return true
67-
}
68-
69-
func stopServer() {
70-
if let server = webServer, server.isRunning {
71-
server.stop()
72-
print("[CertServerManager] Server stopped")
73-
}
74-
webServer = nil
75-
didServeOnce = false
76-
}
77-
78-
deinit {
79-
stopServer()
80-
}
81-
}
823

834
// MARK: - SetupView
845
struct SetupView: View {
856
var onComplete: () -> Void
867

878
@State private var currentPage = 0
88-
@State private var isGeneratingCert = false
89-
@State private var certGenerated = false
90-
@State private var showStartFailedAlert = false
91-
92-
@StateObject private var serverManager = CertServerManager()
939

9410
private let pages: [SetupPage] = [
95-
SetupPage(title: "Welcome to ProStore!",
96-
subtitle: "Before you begin, follow these steps to make sure ProStore works perfectly.",
97-
imageName: "star.fill"),
98-
99-
SetupPage(title: "Install the SSL Certificate",
100-
subtitle: "ProStore will now generate the SSL certificate and open it for installation.\nTap the 'Generate Certificate' button, then when you get redirected, tap the 'Allow' button.\nWhen the popup appears, click the 'Close' button.",
101-
imageName: "lock.shield"),
102-
103-
SetupPage(title: "Install the SSL Certificate",
104-
subtitle: "Go to Settings, tap 'Profile Downloaded', then 'Install'.\nEnter your passcode, and confirm by tapping 'Install' on the popup.",
105-
imageName: "checkmark.shield"),
106-
107-
SetupPage(title: "Install the SSL Certificate",
108-
subtitle: "Tap the tick, then navigate to\n'General → About → Certificate Trust Settings'.\nEnable 'ProStore' under 'Enable Full Trust for Root Certificates'.",
109-
imageName: "hand.thumbsup"),
110-
111-
SetupPage(title: "You're finished!",
112-
subtitle: "Thanks for completing the setup!\nYou're now ready to use ProStore.",
113-
imageName: "party.popper")
11+
SetupPage(
12+
title: "Welcome to ProStore!",
13+
subtitle: "Before you begin, follow these steps to make sure ProStore works perfectly.",
14+
imageName: "star.fill"
15+
),
16+
SetupPage(
17+
title: "Install ProStore Shortcut",
18+
subtitle: "Please install the shorcut below.",
19+
imageName: "shortcut"
20+
),
21+
SetupPage(
22+
title: "You're finished!",
23+
subtitle: "Thanks for completing the setup!\nYou're now ready to use ProStore.",
24+
imageName: "party.popper"
25+
)
11426
]
11527

11628
var body: some View {
@@ -134,19 +46,6 @@ struct SetupView: View {
13446
Text(pages[index].subtitle)
13547
.multilineTextAlignment(.center)
13648
.padding(.horizontal)
137-
138-
if index == 2 && !certGenerated {
139-
if isGeneratingCert {
140-
ProgressView("Generating certificate...")
141-
.padding(.top, 20)
142-
} else {
143-
Button("Generate Certificate") {
144-
generateCertificate()
145-
}
146-
.buttonStyle(.borderedProminent)
147-
.padding(.top, 20)
148-
}
149-
}
15049
}
15150
.tag(index)
15251
}
@@ -170,62 +69,25 @@ struct SetupView: View {
17069

17170
Button(currentPage == pages.count - 1 ? "Finish" : "Next") {
17271
withAnimation {
173-
if currentPage == 2 && !certGenerated {
174-
generateCertificate()
175-
} else if currentPage < pages.count - 1 {
72+
if pages[currentPage].title == "Install ProStore Shortcut",
73+
let shortcutURL = URL(string: "https://raw.githubusercontent.com/ProStore-iOS/files/refs/heads/main/Turn%20on%20VPN.shortcut") {
74+
UIApplication.shared.open(shortcutURL)
75+
}
76+
77+
if currentPage < pages.count - 1 {
17678
currentPage += 1
17779
} else {
17880
onComplete()
17981
}
18082
}
18183
}
182-
.disabled(currentPage == 2 && !certGenerated)
18384
.buttonStyle(.borderedProminent)
18485
}
18586
.padding(.horizontal)
18687

18788
Spacer(minLength: 20)
18889
}
18990
.padding()
190-
.alert("Failed to start local web server", isPresented: $showStartFailedAlert) {
191-
Button("OK", role: .cancel) {}
192-
} message: {
193-
Text("Couldn't start the local web server to serve the certificate. Try again or check logs.")
194-
}
195-
.onDisappear {
196-
serverManager.stopServer()
197-
}
198-
}
199-
200-
// MARK: - Certificate generation
201-
private func generateCertificate() {
202-
isGeneratingCert = true
203-
certGenerated = false
204-
205-
Task {
206-
do {
207-
let urls = try await GenerateCert.createAndSaveCerts()
208-
209-
guard let proStoreCertURL = urls.first(where: {
210-
let name = $0.lastPathComponent.lowercased()
211-
return name == "prostore.pem" || name == "prostore.crt" || name == "prostore.pem.crt"
212-
}) ?? urls.first else {
213-
throw NSError(domain: "GenerateCert", code: -1, userInfo: [NSLocalizedDescriptionKey: "ProStore certificate file not found"])
214-
}
215-
216-
let started = serverManager.serveAndOpen(certURL: proStoreCertURL)
217-
218-
if !started {
219-
showStartFailedAlert = true
220-
} else {
221-
certGenerated = true
222-
}
223-
224-
isGeneratingCert = false
225-
} catch {
226-
isGeneratingCert = false
227-
}
228-
}
22991
}
23092
}
23193

@@ -234,5 +96,4 @@ struct SetupPage {
23496
let title: String
23597
let subtitle: String
23698
let imageName: String
237-
}
238-
99+
}

project.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ targets:
3636
properties:
3737
CFBundleDisplayName: "ProStore"
3838
CFBundleName: "prostore"
39-
CFBundleVersion: "45"
40-
CFBundleShortVersionString: "0.11.0d12"
39+
CFBundleVersion: "46"
40+
CFBundleShortVersionString: "0.12.0d1"
4141
UILaunchStoryboardName: "LaunchScreen"
4242
NSPrincipalClass: "UIApplication"
4343
NSAppTransportSecurity:

0 commit comments

Comments
 (0)