Skip to content

Commit 5fef725

Browse files
committed
New stuff
1 parent e59a9fe commit 5fef725

File tree

6 files changed

+250
-98
lines changed

6 files changed

+250
-98
lines changed

StikDebug.xcodeproj/project.pbxproj

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -719,18 +719,18 @@
719719
"$(PROJECT_DIR)/StikJIT/idevice",
720720
);
721721
MACOSX_DEPLOYMENT_TARGET = 15.1;
722-
MARKETING_VERSION = 2.3.5;
722+
MARKETING_VERSION = 26.0;
723723
PRODUCT_BUNDLE_IDENTIFIER = com.stik.sj;
724724
PRODUCT_NAME = "$(TARGET_NAME)";
725725
SDKROOT = auto;
726-
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
726+
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
727727
SUPPORTS_MACCATALYST = NO;
728-
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
728+
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
729729
SWIFT_EMIT_LOC_STRINGS = YES;
730730
SWIFT_OBJC_BRIDGING_HEADER = "StikJIT/StikJIT-Bridging-Header.h";
731731
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
732732
SWIFT_VERSION = 5.0;
733-
TARGETED_DEVICE_FAMILY = "1,2,7";
733+
TARGETED_DEVICE_FAMILY = "1,2";
734734
XROS_DEPLOYMENT_TARGET = 2.2;
735735
};
736736
name = Debug;
@@ -775,17 +775,17 @@
775775
"$(PROJECT_DIR)/StikJIT/idevice",
776776
);
777777
MACOSX_DEPLOYMENT_TARGET = 15.1;
778-
MARKETING_VERSION = 2.3.5;
778+
MARKETING_VERSION = 26.0;
779779
PRODUCT_BUNDLE_IDENTIFIER = com.stik.sj;
780780
PRODUCT_NAME = "$(TARGET_NAME)";
781781
SDKROOT = auto;
782-
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator";
782+
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
783783
SUPPORTS_MACCATALYST = NO;
784-
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES;
784+
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
785785
SWIFT_EMIT_LOC_STRINGS = YES;
786786
SWIFT_OBJC_BRIDGING_HEADER = "StikJIT/StikJIT-Bridging-Header.h";
787787
SWIFT_VERSION = 5.0;
788-
TARGETED_DEVICE_FAMILY = "1,2,7";
788+
TARGETED_DEVICE_FAMILY = "1,2";
789789
XROS_DEPLOYMENT_TARGET = 2.2;
790790
};
791791
name = Release;

StikJIT/StikJITApp.swift

Lines changed: 72 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -511,20 +511,6 @@ struct HeartbeatApp: App {
511511
@StateObject private var themeExpansionManager = ThemeExpansionManager()
512512
@Environment(\.scenePhase) private var scenePhase // Observe scene lifecycle
513513

514-
let urls: [String] = [
515-
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/BuildManifest.plist",
516-
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg",
517-
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg.trustcache"
518-
]
519-
520-
let outputDir: String = "DDI"
521-
522-
let outputFiles: [String] = [
523-
"DDI/BuildManifest.plist",
524-
"DDI/Image.dmg",
525-
"DDI/Image.dmg.trustcache"
526-
]
527-
528514
init() {
529515
registerAdvancedOptionsDefault()
530516
ContinuedProcessingManager.shared.configureIfNeeded()
@@ -583,16 +569,20 @@ struct HeartbeatApp: App {
583569
BackgroundContainer {
584570
MainTabView()
585571
.onAppear {
586-
let fileManager = FileManager.default
587-
for (index, urlString) in urls.enumerated() {
588-
let destinationURL = URL.documentsDirectory.appendingPathComponent(outputFiles[index])
589-
if !fileManager.fileExists(atPath: destinationURL.path) {
590-
downloadFile(from: urlString, to: destinationURL) { result in
591-
if (result != "") {
572+
Task {
573+
let fileManager = FileManager.default
574+
for item in ddiDownloadItems {
575+
let destinationURL = URL.documentsDirectory.appendingPathComponent(item.relativePath)
576+
if fileManager.fileExists(atPath: destinationURL.path) { continue }
577+
do {
578+
try await downloadFile(from: item.urlString, to: destinationURL)
579+
} catch {
580+
await MainActor.run {
592581
alert_title = "An Error has Occurred"
593-
alert_string = "[Download DDI Error]: " + result
582+
alert_string = "[Download DDI Error]: \(error.localizedDescription)"
594583
show_alert = true
595584
}
585+
break
596586
}
597587
}
598588
}
@@ -961,75 +951,76 @@ public func showAlert(title: String, message: String, showOk: Bool, showTryAgain
961951
}
962952
}
963953

964-
func downloadFile(from urlString: String, to destinationURL: URL, completion: @escaping (String) -> Void) {
965-
let fileManager = FileManager.default
966-
let documentsDirectory = URL.documentsDirectory
967-
968-
guard let url = URL(string: urlString) else {
969-
print("Invalid URL: \(urlString)")
970-
completion("[Internal Invalid URL error]")
971-
return
972-
}
954+
private struct DDIDownloadItem {
955+
let name: String
956+
let relativePath: String
957+
let urlString: String
958+
}
959+
960+
private let ddiDownloadItems: [DDIDownloadItem] = [
961+
.init(
962+
name: "Build Manifest",
963+
relativePath: "DDI/BuildManifest.plist",
964+
urlString: "https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/BuildManifest.plist"
965+
),
966+
.init(
967+
name: "Image",
968+
relativePath: "DDI/Image.dmg",
969+
urlString: "https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg"
970+
),
971+
.init(
972+
name: "TrustCache",
973+
relativePath: "DDI/Image.dmg.trustcache",
974+
urlString: "https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg.trustcache"
975+
)
976+
]
977+
978+
enum DDIDownloadError: LocalizedError {
979+
case invalidURL(String)
973980

974-
let task = URLSession.shared.downloadTask(with: url) { (tempLocalUrl, response, error) in
975-
guard let tempLocalUrl = tempLocalUrl, error == nil else {
976-
print("Error downloading file from \(urlString): \(String(describing: error))")
977-
completion("Are you connected to the internet? [Download Failed]")
978-
return
979-
}
980-
981-
do {
982-
try fileManager.createDirectory(at: destinationURL.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil)
983-
try fileManager.moveItem(at: tempLocalUrl, to: destinationURL)
984-
print("Downloaded \(urlString) to \(destinationURL.path)")
985-
} catch {
986-
print("Error saving file: \(error)")
981+
var errorDescription: String? {
982+
switch self {
983+
case .invalidURL(let string):
984+
return "Invalid download URL: \(string)"
987985
}
988986
}
989-
task.resume()
990-
completion("")
991987
}
992988

993-
func redownloadDDI() {
989+
func downloadFile(from urlString: String, to destinationURL: URL) async throws {
990+
guard let url = URL(string: urlString) else {
991+
throw DDIDownloadError.invalidURL(urlString)
992+
}
993+
let (tempLocalUrl, _) = try await URLSession.shared.download(from: url)
994994
let fileManager = FileManager.default
995-
let ddiFiles = [
996-
"DDI/BuildManifest.plist",
997-
"DDI/Image.dmg",
998-
"DDI/Image.dmg.trustcache"
999-
]
1000-
1001-
for file in ddiFiles {
1002-
let fileURL = URL.documentsDirectory.appendingPathComponent(file)
1003-
if fileManager.fileExists(atPath: fileURL.path) {
1004-
do {
1005-
try fileManager.removeItem(at: fileURL)
1006-
print("Deleted \(file)")
1007-
} catch {
1008-
print("Error deleting \(file): \(error)")
1009-
}
1010-
}
995+
try fileManager.createDirectory(at: destinationURL.deletingLastPathComponent(),
996+
withIntermediateDirectories: true)
997+
if fileManager.fileExists(atPath: destinationURL.path) {
998+
try fileManager.removeItem(at: destinationURL)
1011999
}
1000+
try fileManager.moveItem(at: tempLocalUrl, to: destinationURL)
1001+
}
10121002

1013-
let urls = [
1014-
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/BuildManifest.plist",
1015-
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg",
1016-
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg.trustcache"
1017-
]
1018-
1019-
let group = DispatchGroup()
1020-
1021-
for (index, urlString) in urls.enumerated() {
1022-
let destinationURL = URL.documentsDirectory.appendingPathComponent(ddiFiles[index])
1023-
group.enter()
1024-
downloadFile(from: urlString, to: destinationURL) { result in
1025-
if (result != "") {
1026-
showAlert(title: "An Error has Occurred", message: "[Download DDI Error]: " + result, showOk: true)
1027-
}
1028-
group.leave()
1003+
func redownloadDDI(progressHandler: ((Double, String) -> Void)? = nil) async throws {
1004+
let fileManager = FileManager.default
1005+
let totalStages = Double(ddiDownloadItems.count + 1)
1006+
var completedStages = 0.0
1007+
1008+
progressHandler?(0.0, "Removing existing DDI files…")
1009+
for item in ddiDownloadItems {
1010+
let fileURL = URL.documentsDirectory.appendingPathComponent(item.relativePath)
1011+
if fileManager.fileExists(atPath: fileURL.path) {
1012+
try fileManager.removeItem(at: fileURL)
10291013
}
10301014
}
1031-
1032-
group.notify(queue: .main) {
1033-
showAlert(title: "Success", message: "DDI files have been redownloaded.", showOk: true)
1015+
completedStages += 1.0
1016+
progressHandler?(completedStages / totalStages, "Starting downloads…")
1017+
1018+
for item in ddiDownloadItems {
1019+
progressHandler?(completedStages / totalStages, "Downloading \(item.name)")
1020+
let destinationURL = URL.documentsDirectory.appendingPathComponent(item.relativePath)
1021+
try await downloadFile(from: item.urlString, to: destinationURL)
1022+
completedStages += 1.0
1023+
progressHandler?(completedStages / totalStages, "\(item.name) ready")
10341024
}
1025+
progressHandler?(1.0, "DDI download complete.")
10351026
}

StikJIT/Utilities/ContinuedProcessingManager.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ final class ContinuedProcessingManager {
2525
func configureIfNeeded() {
2626
handler.configureIfNeeded()
2727
}
28+
29+
func cancelPendingTasks() {
30+
handler.cancelPendingTasks()
31+
}
2832

2933
func begin(title: String, subtitle: String) {
3034
handler.begin(title: title, subtitle: subtitle)
@@ -42,6 +46,7 @@ final class ContinuedProcessingManager {
4246
private protocol ContinuedProcessingHandling: AnyObject {
4347
var isSupported: Bool { get }
4448
func configureIfNeeded()
49+
func cancelPendingTasks()
4550
func begin(title: String, subtitle: String)
4651
func updateProgress(_ fraction: Double)
4752
func finish(success: Bool)
@@ -50,6 +55,7 @@ private protocol ContinuedProcessingHandling: AnyObject {
5055
private final class NoopContinuedProcessingHandler: ContinuedProcessingHandling {
5156
var isSupported: Bool { false }
5257
func configureIfNeeded() {}
58+
func cancelPendingTasks() {}
5359
func begin(title: String, subtitle: String) {}
5460
func updateProgress(_ fraction: Double) {}
5561
func finish(success: Bool) {}
@@ -95,6 +101,8 @@ private final class ModernContinuedProcessingHandler: ContinuedProcessingHandlin
95101
}
96102
}
97103
guard reserved else { return }
104+
// Clear any stale request that might block new submissions.
105+
scheduler.cancel(taskRequestWithIdentifier: taskIdentifier)
98106
let request = BGContinuedProcessingTaskRequest(identifier: taskIdentifier,
99107
title: title,
100108
subtitle: subtitle)
@@ -110,6 +118,18 @@ private final class ModernContinuedProcessingHandler: ContinuedProcessingHandlin
110118
}
111119
}
112120

121+
func cancelPendingTasks() {
122+
queue.async { [weak self] in
123+
guard let self else { return }
124+
if let task = activeTask {
125+
task.setTaskCompleted(success: false)
126+
activeTask = nil
127+
}
128+
pendingMetadata = nil
129+
scheduler.cancel(taskRequestWithIdentifier: taskIdentifier)
130+
}
131+
}
132+
113133
func updateProgress(_ fraction: Double) {
114134
queue.async { [weak self] in
115135
guard let task = self?.activeTask else { return }

StikJIT/Views/HomeView.swift

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,32 @@ struct HomeView: View {
9191
!ddiMounted &&
9292
!heartbeatOK
9393
}
94+
private var sanitizedUsername: String {
95+
let trimmed = username.trimmingCharacters(in: .whitespacesAndNewlines)
96+
return trimmed.isEmpty ? "there" : trimmed
97+
}
98+
private var greetingTitle: String {
99+
"\(timeOfDayGreeting), \(sanitizedUsername)!"
100+
}
101+
private var greetingSubtitle: String {
102+
if canConnectByApp {
103+
return "You're all set. Connect whenever you're ready."
104+
} else if !pairingFileExists {
105+
return "Import your pairing file to start debugging."
106+
} else if !ddiMounted {
107+
return "Mount the DDI to finish preparing your device."
108+
}
109+
return "Complete the steps below to get ready."
110+
}
111+
private var timeOfDayGreeting: String {
112+
let hour = Calendar.current.component(.hour, from: Date())
113+
switch hour {
114+
case 5..<12: return "Good morning"
115+
case 12..<17: return "Good afternoon"
116+
case 17..<22: return "Good evening"
117+
default: return "Hello"
118+
}
119+
}
94120
private var shouldPromptForWiFi: Bool {
95121
pairingFileLikelyInvalid && !wifiConnected && isCellularActive
96122
}
@@ -105,6 +131,7 @@ struct HomeView: View {
105131

106132
ScrollView {
107133
VStack(spacing: 20) {
134+
welcomeCard
108135
setupCard
109136
connectCard
110137
// if pairingFileExists {
@@ -352,6 +379,20 @@ struct HomeView: View {
352379

353380
// MARK: - Styled Sections
354381

382+
private var welcomeCard: some View {
383+
homeCard {
384+
VStack(alignment: .leading, spacing: 6) {
385+
Text(greetingTitle)
386+
.font(.system(.title2, design: .rounded).weight(.semibold))
387+
.foregroundStyle(.primary)
388+
Text(greetingSubtitle)
389+
.font(.subheadline)
390+
.foregroundStyle(.secondary)
391+
}
392+
.frame(maxWidth: .infinity, alignment: .leading)
393+
}
394+
}
395+
355396
private var setupCard: some View {
356397
homeCard {
357398
VStack(alignment: .leading, spacing: 16) {

0 commit comments

Comments
 (0)