Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 77 additions & 20 deletions StikJIT/Views/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct HomeView: View {
@State private var viewDidAppeared = false
@State private var pendingBundleIdToEnableJIT : String? = nil
@State private var pendingPIDToEnableJIT : Int? = nil
@State private var isDebugging = false

private var accentColor: Color {
if customAccentColorHex.isEmpty {
Expand Down Expand Up @@ -145,6 +146,27 @@ struct HomeView: View {
.sheet(isPresented: $showingConsoleLogsView) {
ConsoleLogsView()
}

if isDebugging {
Button(action: {
detachDebugSession()
}) {
HStack {
Image(systemName: "eject.fill")
.font(.system(size: 20))
Text("Detach Debugger")
.font(.system(.title3, design: .rounded))
.fontWeight(.semibold)
}
.frame(maxWidth: .infinity)
.padding()
.background(accentColor)
.foregroundColor(accentColor.contrastText())
.cornerRadius(16)
.shadow(color: accentColor.opacity(0.3), radius: 8, x: 0, y: 4)
}
.padding(.horizontal, 20)
}

// Status message area - keeps layout consistent
ZStack {
Expand Down Expand Up @@ -380,20 +402,29 @@ struct HomeView: View {
LogManager.shared.addInfoLog("Starting Debug for \(bundleID)")

DispatchQueue.global(qos: .background).async {

let success = JITEnableContext.shared.debugApp(withBundleID: bundleID, logger: { message in

if let message = message {
// Log messages from the JIT process
LogManager.shared.addInfoLog(message)
}
})
let os = ProcessInfo.processInfo.operatingSystemVersion
let success: Bool
if os.majorVersion >= 19 {
success = JITEnableContext.shared.startDebugSession(withBundleID: bundleID, logger: { message in
if let message = message {
LogManager.shared.addInfoLog(message)
}
})
} else {
success = JITEnableContext.shared.debugApp(withBundleID: bundleID, logger: { message in
if let message = message {
LogManager.shared.addInfoLog(message)
}
})
}

DispatchQueue.main.async {
LogManager.shared.addInfoLog("Debug process completed for \(bundleID)")
isProcessing = false

if success && doAutoQuitAfterEnablingJIT {

if os.majorVersion >= 19 {
if success { isDebugging = true }
} else if success && doAutoQuitAfterEnablingJIT {
exit(0)
}
}
Expand All @@ -407,26 +438,52 @@ struct HomeView: View {
LogManager.shared.addInfoLog("Starting JIT for pid \(pid)")

DispatchQueue.global(qos: .background).async {

let success = JITEnableContext.shared.debugApp(withPID: Int32(pid), logger: { message in

if let message = message {
// Log messages from the JIT process
LogManager.shared.addInfoLog(message)
}
})
let os = ProcessInfo.processInfo.operatingSystemVersion
let success: Bool
if os.majorVersion >= 19 {
success = JITEnableContext.shared.startDebugSession(withPID: Int32(pid), logger: { message in
if let message = message {
LogManager.shared.addInfoLog(message)
}
})
} else {
success = JITEnableContext.shared.debugApp(withPID: Int32(pid), logger: { message in
if let message = message {
LogManager.shared.addInfoLog(message)
}
})
}

DispatchQueue.main.async {
LogManager.shared.addInfoLog("JIT process completed for \(pid)")
showAlert(title: "Success", message: "JIT has been enabled for pid \(pid).", showOk: true, messageType: .success, completion: { _ in })
isProcessing = false

if success && doAutoQuitAfterEnablingJIT {

if os.majorVersion >= 19 {
if success { isDebugging = true }
} else if success && doAutoQuitAfterEnablingJIT {
exit(0)
}
}
}
}

private func detachDebugSession() {
isProcessing = true

DispatchQueue.global(qos: .background).async {
JITEnableContext.shared.detachDebugSession { message in
if let message = message {
LogManager.shared.addInfoLog(message)
}
}

DispatchQueue.main.async {
isProcessing = false
isDebugging = false
}
}
}
}

class InstalledAppsViewModel: ObservableObject {
Expand Down
3 changes: 3 additions & 0 deletions StikJIT/idevice/JITEnableContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ typedef void (^LogFunc)(NSString *message);
- (void)startHeartbeatWithCompletionHandler:(HeartbeatCompletionHandler)completionHandler logger:(LogFunc)logger;
- (BOOL)debugAppWithBundleID:(NSString*)bundleID logger:(LogFunc)logger;
- (BOOL)debugAppWithPID:(int)pid logger:(LogFunc)logger;
- (BOOL)startDebugSessionWithBundleID:(NSString*)bundleID logger:(LogFunc)logger;
- (BOOL)startDebugSessionWithPID:(int)pid logger:(LogFunc)logger;
- (void)detachDebugSession:(LogFunc)logger;
- (NSDictionary<NSString*, NSString*>*)getAppListWithError:(NSError**)error;
- (UIImage*)getAppIconWithBundleId:(NSString*)bundleId error:(NSError**)error;
@end
36 changes: 36 additions & 0 deletions StikJIT/idevice/JITEnableContext.m
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,42 @@ - (BOOL)debugAppWithPID:(int)pid logger:(LogFunc)logger {
[self createCLogger:logger]) == 0;
}

- (BOOL)startDebugSessionWithBundleID:(NSString*)bundleID logger:(LogFunc)logger {
if (!provider) {
if (logger) {
logger(@"Provider not initialized!");
}
NSLog(@"Provider not initialized!");
return NO;
}

[self ensureHeartbeat];

return start_debug_session(provider,
[bundleID UTF8String],
[self createCLogger:logger]) == 0;
}

- (BOOL)startDebugSessionWithPID:(int)pid logger:(LogFunc)logger {
if (!provider) {
if (logger) {
logger(@"Provider not initialized!");
}
NSLog(@"Provider not initialized!");
return NO;
}

[self ensureHeartbeat];

return start_debug_session_pid(provider,
pid,
[self createCLogger:logger]) == 0;
}

- (void)detachDebugSession:(LogFunc)logger {
detach_debug_session([self createCLogger:logger]);
}

- (NSDictionary<NSString*, NSString*>*)getAppListWithError:(NSError**)error {
if (!provider) {
NSLog(@"Provider not initialized!");
Expand Down
Loading