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

Commit f95812a

Browse files
authored
Add files via upload
1 parent 7e7fea6 commit f95812a

3 files changed

Lines changed: 58 additions & 162 deletions

File tree

Lines changed: 13 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,22 @@
11
// installApp.swift
22
import Foundation
3-
import Combine
43
import IDeviceSwift
54

6-
// First, let's define the correct InstallerStatus enum if it doesn't exist elsewhere
7-
public enum InstallerStatus {
8-
case idle
9-
case uploading(percent: Int)
10-
case installing(percent: Int)
11-
case success
12-
case failure(message: String)
13-
case message(String)
14-
15-
public var pretty: String {
16-
switch self {
17-
case .idle:
18-
return "Idle"
19-
case .uploading(let percent):
20-
return "Uploading... (\(percent)%)"
21-
case .installing(let percent):
22-
return "Installing... (\(percent)%)"
23-
case .success:
24-
return "✅ Success!"
25-
case .failure(let message):
26-
return "\(message)"
27-
case .message(let text):
28-
return text
29-
}
30-
}
31-
}
5+
/// Installs a signed IPA on the device using InstallationProxy
6+
public func installApp(from ipaURL: URL) async throws {
7+
print("Installing app from: \(ipaURL.path)")
328

33-
// InstallerStatusViewModel with the correct enum
34-
public class InstallerStatusViewModel: ObservableObject {
35-
@Published public var status: InstallerStatus = .idle
36-
@Published public var uploadProgress: Double = 0.0
37-
@Published public var installProgress: Double = 0.0
38-
// ... other properties as needed
39-
}
9+
// Start heartbeat to keep connection alive during long install
10+
HeartbeatManager.shared.start()
4011

41-
public func installAppWithStatusStream(from ipaURL: URL) -> AsyncThrowingStream<InstallerStatus, Error> {
42-
AsyncThrowingStream { continuation in
43-
// create a local view model for the InstallationProxy internals
44-
let localVM = InstallerStatusViewModel()
45-
var cancellables = Set<AnyCancellable>()
12+
// Create view model to receive installation status updates
13+
let viewModel = InstallerStatusViewModel()
4614

47-
// Observe progress and forward into the AsyncStream
48-
localVM.$uploadProgress
49-
.sink { progress in
50-
let pct = Int(progress * 100)
51-
continuation.yield(.uploading(percent: pct))
52-
}
53-
.store(in: &cancellables)
15+
// Create the installation proxy
16+
let installer = await InstallationProxy(viewModel: viewModel)
5417

55-
localVM.$installProgress
56-
.sink { progress in
57-
let pct = Int(progress * 100)
58-
continuation.yield(.installing(percent: pct))
59-
}
60-
.store(in: &cancellables)
18+
// Perform the actual installation
19+
try await installer.install(at: ipaURL)
6120

62-
// Optionally map other status changes
63-
localVM.$status
64-
.sink { status in
65-
continuation.yield(status)
66-
}
67-
.store(in: &cancellables)
68-
69-
Task {
70-
do {
71-
let installer = InstallationProxy(viewModel: localVM)
72-
try await installer.install(at: ipaURL)
73-
continuation.yield(.success)
74-
continuation.finish()
75-
} catch {
76-
// forward failure as an enum + error finishing
77-
continuation.yield(.failure(message: error.localizedDescription))
78-
continuation.finish(throwing: error)
79-
}
80-
}
81-
82-
// on stream termination, cancel Combine sinks
83-
continuation.onTermination = { @Sendable _ in
84-
cancellables.forEach { $0.cancel() }
85-
}
86-
}
87-
}
21+
print("Installation completed successfully!")
22+
}

Sources/prostore/signing/DownloadSignManager.swift

Lines changed: 43 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ class DownloadSignManager: ObservableObject {
1111
private var downloadTask: URLSessionDownloadTask?
1212
private var cancellables = Set<AnyCancellable>()
1313

14-
// Assuming signer is available - you might need to import it
15-
private let signer = signer()
16-
1714
func downloadAndSign(app: AltApp) {
1815
guard let downloadURL = app.downloadURL else {
1916
self.status = "No download URL available"
@@ -71,7 +68,7 @@ class DownloadSignManager: ObservableObject {
7168
}
7269

7370
// Step 4: Sign the IPA
74-
self.signAndInstallIPA(ipaURL: tempIPAURL, p12URL: p12URL, provURL: provURL, password: password, appName: appName)
71+
self.signIPA(ipaURL: tempIPAURL, p12URL: p12URL, provURL: provURL, password: password, appName: appName)
7572

7673
case .failure(let error):
7774
DispatchQueue.main.async {
@@ -156,95 +153,60 @@ class DownloadSignManager: ObservableObject {
156153
}
157154
}
158155

159-
private func signAndInstallIPA(
160-
ipaURL: URL,
161-
p12URL: URL,
162-
provURL: URL,
163-
password: String,
164-
appName: String
165-
) {
166-
DispatchQueue.main.async {
167-
self.status = "Starting signing process..."
168-
self.progress = 0.5
169-
self.isProcessing = true
170-
}
171-
172-
// Assuming signer.sign method exists
173-
// You'll need to adjust this based on your actual signer implementation
174-
signer.sign(
175-
ipaURL: ipaURL,
176-
p12URL: p12URL,
177-
provURL: provURL,
178-
p12Password: password,
179-
progressUpdate: { [weak self] status, progress in
180-
DispatchQueue.main.async {
181-
let overallProgress = 0.5 + (progress * 0.5)
182-
self?.progress = overallProgress
183-
let percent = Int(overallProgress * 100)
184-
self?.status = "\(status) (\(percent)%)"
185-
}
186-
},
187-
completion: { [weak self] result in
188-
guard let self = self else { return }
189-
156+
private func signIPA(ipaURL: URL, p12URL: URL, provURL: URL, password: String, appName: String) {
157+
DispatchQueue.main.async {
158+
self.status = "Starting signing process..."
159+
self.progress = 0.5
160+
}
161+
162+
signer.sign(
163+
ipaURL: ipaURL,
164+
p12URL: p12URL,
165+
provURL: provURL,
166+
p12Password: password,
167+
progressUpdate: { [weak self] status, progress in
168+
DispatchQueue.main.async {
169+
let overallProgress = 0.5 + (progress * 0.5)
170+
self?.progress = overallProgress
171+
let percent = Int(overallProgress * 100)
172+
self?.status = "\(status) (\(percent)%)"
173+
}
174+
},
175+
completion: { [weak self] result in
176+
DispatchQueue.main.async {
190177
switch result {
191178
case .success(let signedIPAURL):
192-
DispatchQueue.main.async {
193-
self.progress = 1.0
194-
self.status = "✅ Successfully signed IPA! Installing app now..."
195-
self.showSuccess = true
196-
}
197-
198-
// Install the signed IPA
199-
let stream = installAppWithStatusStream(from: signedIPAURL)
200-
179+
self?.progress = 1.0
180+
self?.status = "✅ Successfully signed ipa! Installing app now..."
181+
self?.showSuccess = true
182+
201183
Task {
202184
do {
203-
for try await status in stream {
204-
DispatchQueue.main.async {
205-
switch status {
206-
case .idle:
207-
break
208-
case .uploading(let pct), .installing(let pct):
209-
self.progress = Double(pct) / 100.0
210-
self.status = status.pretty
211-
case .success:
212-
self.status = status.pretty
213-
// Optional: Delay resetting to show success
214-
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
215-
self.isProcessing = false
216-
self.showSuccess = false
217-
self.progress = 0.0
218-
}
219-
case .failure(let msg):
220-
self.status = status.pretty
221-
self.isProcessing = false
222-
case .message(let text):
223-
self.status = text
224-
}
225-
}
226-
}
185+
try await installApp(from: signedIPAURL)
227186
} catch {
228-
DispatchQueue.main.async {
229-
self.status = "❌ Install failed: \(error.localizedDescription)"
230-
self.isProcessing = false
231-
}
187+
self?.status = "❌ Install failed: \(error.localizedDescription)"
232188
}
233189
}
234190

191+
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
192+
self?.isProcessing = false
193+
self?.showSuccess = false
194+
self?.progress = 0.0
195+
self?.status = ""
196+
}
197+
235198
// Clean up original downloaded IPA
236199
try? FileManager.default.removeItem(at: ipaURL)
237-
200+
238201
case .failure(let error):
239-
DispatchQueue.main.async {
240-
self.status = "❌ Signing failed: \(error.localizedDescription)"
241-
self.isProcessing = false
242-
try? FileManager.default.removeItem(at: ipaURL)
243-
}
202+
self?.status = "❌ Signing failed: \(error.localizedDescription)"
203+
self?.isProcessing = false
204+
try? FileManager.default.removeItem(at: ipaURL)
244205
}
245206
}
246-
)
247-
}
207+
}
208+
)
209+
}
248210

249211
func cancel() {
250212
downloadTask?.cancel()
@@ -264,5 +226,4 @@ class DownloadSignManager: ObservableObject {
264226
}
265227
return appFolder
266228
}
267-
}
268-
229+
}

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: "52"
40-
CFBundleShortVersionString: "0.12.0d7"
39+
CFBundleVersion: "51"
40+
CFBundleShortVersionString: "0.12.0d6"
4141
UILaunchStoryboardName: "LaunchScreen"
4242
NSPrincipalClass: "UIApplication"
4343
NSAppTransportSecurity:

0 commit comments

Comments
 (0)