mirror of
https://github.com/StikDebug/StikDebug.git
synced 2026-10-16 12:30:29 +00:00
Merge pull request #5 from stossy11/main
Add Heartbeat Completion Handler
This commit is contained in:
commit
b76c6581ff
5 changed files with 142 additions and 11 deletions
|
|
@ -7,24 +7,77 @@
|
|||
|
||||
import SwiftUI
|
||||
import em_proxy
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
@main
|
||||
struct HeartbeatApp: App {
|
||||
@State private var isLoading = true
|
||||
@State private var isPairing = false
|
||||
@State private var heartBeat = false
|
||||
@State private var error: Int32? = nil
|
||||
|
||||
init() {
|
||||
let fixMethod = class_getInstanceMethod(UIDocumentPickerViewController.self, #selector(UIDocumentPickerViewController.fix_init(forOpeningContentTypes:asCopy:)))!
|
||||
let origMethod = class_getInstanceMethod(UIDocumentPickerViewController.self, #selector(UIDocumentPickerViewController.init(forOpeningContentTypes:asCopy:)))!
|
||||
method_exchangeImplementations(origMethod, fixMethod)
|
||||
}
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
if isLoading {
|
||||
LoadingView()
|
||||
.onAppear {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
|
||||
withAnimation(.easeInOut(duration: 1.0)) {
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
startProxy()
|
||||
if FileManager.default.fileExists(atPath: URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path) {
|
||||
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
|
||||
if heartBeat {
|
||||
isLoading = false
|
||||
timer.invalidate()
|
||||
} else {
|
||||
if let error {
|
||||
if error == InvalidHostID.rawValue {
|
||||
isPairing = true
|
||||
} else {
|
||||
startHeartbeatInBackground()
|
||||
}
|
||||
self.error = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startHeartbeatInBackground()
|
||||
} else {
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
.fileImporter(isPresented: $isPairing, allowedContentTypes: [UTType(filenameExtension: "mobiledevicepairing", conformingTo: .data)!, .propertyList]) {result in
|
||||
switch result {
|
||||
|
||||
case .success(let url):
|
||||
let fileManager = FileManager.default
|
||||
let accessing = url.startAccessingSecurityScopedResource()
|
||||
|
||||
if fileManager.fileExists(atPath: url.path) {
|
||||
do {
|
||||
if fileManager.fileExists(atPath: URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path) {
|
||||
try fileManager.removeItem(at: URL.documentsDirectory.appendingPathComponent("pairingFile.plist"))
|
||||
}
|
||||
|
||||
try fileManager.copyItem(at: url, to: URL.documentsDirectory.appendingPathComponent("pairingFile.plist"))
|
||||
print("File copied successfully!")
|
||||
startHeartbeatInBackground()
|
||||
} catch {
|
||||
print("Error copying file: \(error)")
|
||||
}
|
||||
} else {
|
||||
print("Source file does not exist.")
|
||||
}
|
||||
|
||||
if accessing {
|
||||
url.stopAccessingSecurityScopedResource()
|
||||
}
|
||||
case .failure(_):
|
||||
print("Failed")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -50,16 +103,57 @@ struct HeartbeatApp: App {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func startHeartbeatInBackground() {
|
||||
let heartBeat = Thread {
|
||||
let cCompletionHandler: @convention(block) (Int32, UnsafePointer<CChar>?) -> Void = { result, messagePointer in
|
||||
let message: String? = messagePointer != nil ? String(cString: messagePointer!) : nil
|
||||
|
||||
if result == 0 {
|
||||
print("Heartbeat started successfully: \(message ?? "")")
|
||||
|
||||
self.heartBeat = true
|
||||
} else {
|
||||
print("Error: \(result == InvalidHostID.rawValue ? "Invalid host ID, Please Selecr New Pairing File" : message ?? "") (Code: \(result))")
|
||||
|
||||
showAlert(title: "HeartBeat Error", message: "\(message ?? "") (\(result))", showOk: true) { _ in
|
||||
self.error = result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startHeartbeat(cCompletionHandler)
|
||||
}
|
||||
|
||||
heartBeat.qualityOfService = .background
|
||||
heartBeat.name = "HeartBeat"
|
||||
heartBeat.start()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func startHeartbeatInBackground() {
|
||||
let heartBeat = Thread {
|
||||
startHeartbeat()
|
||||
let cCompletionHandler: @convention(block) (Int32, UnsafePointer<CChar>?) -> Void = { result, messagePointer in
|
||||
let message: String? = messagePointer != nil ? String(cString: messagePointer!) : nil
|
||||
|
||||
if result == 0 {
|
||||
print("Heartbeat started successfully: \(message ?? "")")
|
||||
} else {
|
||||
print("Error: \(message ?? "") (Code: \(result))")
|
||||
|
||||
showAlert(title: "HeartBeat Error", message: "\(message ?? "") (\(result))", showOk: true) { _ in
|
||||
startHeartbeatInBackground()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startHeartbeat(cCompletionHandler)
|
||||
}
|
||||
|
||||
heartBeat.qualityOfService = .background
|
||||
heartBeat.name = "HeartBeat"
|
||||
heartBeat.name = "Heartbeat"
|
||||
heartBeat.start()
|
||||
}
|
||||
|
||||
|
|
@ -106,3 +200,23 @@ struct LoadingView: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func showAlert(title: String, message: String, showOk: Bool, completion: @escaping (Bool) -> Void) {
|
||||
DispatchQueue.main.async {
|
||||
if let mainWindow = UIApplication.shared.windows.last {
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
|
||||
if showOk {
|
||||
let okAction = UIAlertAction(title: "OK", style: .default) { _ in
|
||||
completion(true)
|
||||
}
|
||||
|
||||
alert.addAction(okAction)
|
||||
} else {
|
||||
completion(false)
|
||||
}
|
||||
|
||||
mainWindow.rootViewController?.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
extension UIDocumentPickerViewController {
|
||||
@objc func fix_init(forOpeningContentTypes contentTypes: [UTType], asCopy: Bool) -> UIDocumentPickerViewController {
|
||||
return fix_init(forOpeningContentTypes: contentTypes, asCopy: true)
|
||||
}
|
||||
}
|
||||
|
||||
struct HomeView: View {
|
||||
@AppStorage("username") private var username = "User"
|
||||
|
|
@ -61,7 +68,7 @@ struct HomeView: View {
|
|||
.onReceive(timer) { _ in
|
||||
refreshBackground()
|
||||
}
|
||||
.fileImporter(isPresented: $isShowingPairingFilePicker, allowedContentTypes: [.item]) {result in
|
||||
.fileImporter(isPresented: $isShowingPairingFilePicker, allowedContentTypes: [UTType(filenameExtension: "mobiledevicepairing", conformingTo: .data)!, .propertyList]) {result in
|
||||
switch result {
|
||||
|
||||
case .success(let url):
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import SwiftUI
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
struct SettingsView: View {
|
||||
@AppStorage("username") private var username = "User"
|
||||
|
|
@ -111,7 +112,7 @@ struct SettingsView: View {
|
|||
.font(.bodyFont)
|
||||
.accentColor(.accentColor)
|
||||
}
|
||||
.fileImporter(isPresented: $isShowingPairingFilePicker, allowedContentTypes: [.item]) {result in
|
||||
.fileImporter(isPresented: $isShowingPairingFilePicker, allowedContentTypes: [UTType(filenameExtension: "mobiledevicepairing", conformingTo: .data)!, .propertyList]) {result in
|
||||
switch result {
|
||||
|
||||
case .success(let url):
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@
|
|||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <limits.h>
|
||||
|
||||
void startHeartbeat() {
|
||||
typedef void (^HeartbeatCompletionHandler)(int result, const char *message);
|
||||
|
||||
void startHeartbeat(HeartbeatCompletionHandler completion) {
|
||||
printf("DEBUG: Initializing logger...\n");
|
||||
idevice_init_logger(Debug, Disabled, NULL);
|
||||
|
||||
|
|
@ -43,6 +45,7 @@ void startHeartbeat() {
|
|||
IdeviceErrorCode err = idevice_pairing_file_read(pairingFilePath, &pairing_file);
|
||||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "DEBUG: Failed to read pairing file: %d\n", err);
|
||||
completion(err, "Failed to read pairing file");
|
||||
return;
|
||||
}
|
||||
printf("DEBUG: Pairing file read successfully.\n");
|
||||
|
|
@ -54,6 +57,7 @@ void startHeartbeat() {
|
|||
if (err != IdeviceSuccess) {
|
||||
fprintf(stderr, "DEBUG: Failed to create TCP provider: %d\n", err);
|
||||
idevice_pairing_file_free(pairing_file);
|
||||
completion(err, "Failed to create TCP provider");
|
||||
return;
|
||||
}
|
||||
printf("DEBUG: TCP provider created successfully.\n");
|
||||
|
|
@ -62,12 +66,15 @@ void startHeartbeat() {
|
|||
HeartbeatClientHandle *client = NULL;
|
||||
err = heartbeat_connect_tcp(provider, &client);
|
||||
if (err != IdeviceSuccess) {
|
||||
completion(err, "Failed to connect to Heartbeat");
|
||||
fprintf(stderr, "DEBUG: Failed to connect to installation proxy: %d\n", err);
|
||||
return;
|
||||
}
|
||||
tcp_provider_free(provider);
|
||||
printf("DEBUG: Connected to installation proxy successfully.\n");
|
||||
|
||||
completion(0, "Heartbeat Completed");
|
||||
|
||||
u_int64_t current_interval = 15;
|
||||
while (1) {
|
||||
u_int64_t new_interval = 0;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#ifndef HEARTBEAT_H
|
||||
#define HEARTBEAT_H
|
||||
|
||||
void startHeartbeat();
|
||||
typedef void (^HeartbeatCompletionHandler)(int result, const char *message);
|
||||
|
||||
void startHeartbeat(HeartbeatCompletionHandler completion);
|
||||
|
||||
#endif /* HEARTBEAT_H */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue