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

Commit c56e792

Browse files
authored
Fix
1 parent 0148477 commit c56e792

2 files changed

Lines changed: 71 additions & 45 deletions

File tree

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,37 @@
1-
// installApp.swift
2-
import Foundation
3-
import IDeviceSwift
1+
import Combine
42

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)")
8-
9-
// Start heartbeat to keep connection alive during long install
10-
HeartbeatManager.shared.start()
11-
12-
// Create view model to receive installation status updates
3+
public func installAppWithStatus(from ipaURL: URL) async throws {
134
let viewModel = InstallerStatusViewModel()
14-
15-
// Create the installation proxy
16-
let installer = await InstallationProxy(viewModel: viewModel)
17-
18-
// Perform the actual installation
5+
6+
// Connect Combine publishers to your UI
7+
var cancellables = Set<AnyCancellable>()
8+
9+
viewModel.$uploadProgress
10+
.sink { [weak self] progress in
11+
DispatchQueue.main.async {
12+
self?.status = "📦 Uploading: \(Int(progress * 100))%"
13+
self?.progress = 0.5 + (progress * 0.25) // optional fine-tune
14+
}
15+
}
16+
.store(in: &cancellables)
17+
18+
viewModel.$installProgress
19+
.sink { [weak self] progress in
20+
DispatchQueue.main.async {
21+
self?.status = "📲 Installing: \(Int(progress * 100))%"
22+
self?.progress = 0.75 + (progress * 0.25) // optional fine-tune
23+
}
24+
}
25+
.store(in: &cancellables)
26+
27+
viewModel.$status
28+
.sink { [weak self] status in
29+
DispatchQueue.main.async {
30+
self?.status = status
31+
}
32+
}
33+
.store(in: &cancellables)
34+
35+
let installer = InstallationProxy(viewModel: viewModel)
1936
try await installer.install(at: ipaURL)
20-
21-
print("Installation completed successfully!")
2237
}

Sources/prostore/signing/DownloadSignManager.swift

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,11 @@ class DownloadSignManager: ObservableObject {
153153
}
154154
}
155155

156-
private func signIPA(ipaURL: URL, p12URL: URL, provURL: URL, password: String, appName: String) {
156+
private func signAndInstallIPA(ipaURL: URL, p12URL: URL, provURL: URL, password: String, appName: String) {
157157
DispatchQueue.main.async {
158158
self.status = "Starting signing process..."
159159
self.progress = 0.5
160+
self.isProcessing = true
160161
}
161162

162163
signer.sign(
@@ -173,34 +174,44 @@ private func signIPA(ipaURL: URL, p12URL: URL, provURL: URL, password: String, a
173174
}
174175
},
175176
completion: { [weak self] result in
176-
DispatchQueue.main.async {
177-
switch result {
178-
case .success(let signedIPAURL):
179-
self?.progress = 1.0
180-
self?.status = "✅ Successfully signed ipa! Installing app now..."
181-
self?.showSuccess = true
182-
183-
Task {
184-
do {
185-
try await installApp(from: signedIPAURL)
186-
} catch {
187-
self?.status = "❌ Install failed: \(error.localizedDescription)"
177+
guard let self else { return }
178+
179+
switch result {
180+
case .success(let signedIPAURL):
181+
DispatchQueue.main.async {
182+
self.progress = 1.0
183+
self.status = "✅ Successfully signed IPA! Installing app now..."
184+
self.showSuccess = true
185+
}
186+
187+
Task {
188+
do {
189+
// Show install status while installing
190+
try await self.installAppWithStatus(from: signedIPAURL)
191+
192+
// Hide the bar 3 seconds AFTER install is complete
193+
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
194+
self.isProcessing = false
195+
self.showSuccess = false
196+
self.progress = 0.0
197+
self.status = ""
198+
}
199+
200+
} catch {
201+
DispatchQueue.main.async {
202+
self.status = "❌ Install failed: \(error.localizedDescription)"
203+
self.isProcessing = false
188204
}
189205
}
190-
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-
198-
// Clean up original downloaded IPA
199-
try? FileManager.default.removeItem(at: ipaURL)
200-
201-
case .failure(let error):
202-
self?.status = "❌ Signing failed: \(error.localizedDescription)"
203-
self?.isProcessing = false
206+
}
207+
208+
// Clean up original downloaded IPA
209+
try? FileManager.default.removeItem(at: ipaURL)
210+
211+
case .failure(let error):
212+
DispatchQueue.main.async {
213+
self.status = "❌ Signing failed: \(error.localizedDescription)"
214+
self.isProcessing = false
204215
try? FileManager.default.removeItem(at: ipaURL)
205216
}
206217
}

0 commit comments

Comments
 (0)