mirror of
https://github.com/StikDebug/StikDebug.git
synced 2026-10-15 20:10:30 +00:00
126 lines
3.4 KiB
Swift
126 lines
3.4 KiB
Swift
//
|
|
// MountingProgress.swift
|
|
// StikDebug
|
|
//
|
|
|
|
import Foundation
|
|
import idevice
|
|
|
|
final class MountingProgress: ObservableObject {
|
|
static let shared = MountingProgress()
|
|
|
|
@Published private(set) var mountingThread: Thread?
|
|
@Published private(set) var coolisMounted: Bool = false
|
|
|
|
private let mountCheckLock = NSLock()
|
|
private var mountCheckInProgress = false
|
|
private let mountLock = NSLock()
|
|
private var mountInProgress = false
|
|
|
|
private init() {}
|
|
|
|
func checkforMounted() {
|
|
guard TunnelManager.shared.isConnected else { return }
|
|
|
|
mountCheckLock.lock()
|
|
guard !mountCheckInProgress else {
|
|
mountCheckLock.unlock()
|
|
return
|
|
}
|
|
mountCheckInProgress = true
|
|
mountCheckLock.unlock()
|
|
|
|
DispatchQueue.global(qos: .utility).async {
|
|
let status = checkMountStatus()
|
|
|
|
self.mountCheckLock.lock()
|
|
self.mountCheckInProgress = false
|
|
self.mountCheckLock.unlock()
|
|
|
|
DispatchQueue.main.async {
|
|
if status != .unreachable {
|
|
self.coolisMounted = status == .mounted
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func pubMount() {
|
|
guard TunnelManager.shared.isConnected, DeveloperDiskImageService.filesAreReady else { return }
|
|
|
|
mountLock.lock()
|
|
guard !mountInProgress else {
|
|
mountLock.unlock()
|
|
return
|
|
}
|
|
mountInProgress = true
|
|
mountLock.unlock()
|
|
|
|
let thread = Thread { [weak self] in
|
|
self?.mount()
|
|
}
|
|
thread.qualityOfService = .background
|
|
thread.name = "mounting"
|
|
DispatchQueue.main.async {
|
|
self.mountingThread = thread
|
|
}
|
|
thread.start()
|
|
}
|
|
|
|
private func mount() {
|
|
switch checkMountStatus() {
|
|
case .mounted:
|
|
finishMount {
|
|
self.coolisMounted = true
|
|
}
|
|
return
|
|
case .unreachable:
|
|
finishMount()
|
|
return
|
|
case .notMounted:
|
|
break
|
|
}
|
|
|
|
guard isPairing() else {
|
|
finishMount()
|
|
return
|
|
}
|
|
|
|
let mountError = mountDeveloperDiskImage(from: DeveloperDiskImageService.directoryURL.path)
|
|
let mounted = mountError == nil || checkMountStatus() == .mounted
|
|
finishMount {
|
|
if mounted {
|
|
self.coolisMounted = true
|
|
self.checkforMounted()
|
|
} else if let mountError {
|
|
LogManager.shared.addErrorLog("Failed to mount DDI: \(mountError)")
|
|
showAlert(title: "DDI Mount Failed", message: mountError, showOk: true, showTryAgain: true) { shouldTryAgain in
|
|
if shouldTryAgain {
|
|
self.pubMount()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func finishMount(_ completion: @escaping () -> Void = {}) {
|
|
DispatchQueue.main.async {
|
|
self.mountingThread = nil
|
|
self.mountLock.lock()
|
|
self.mountInProgress = false
|
|
self.mountLock.unlock()
|
|
completion()
|
|
}
|
|
}
|
|
}
|
|
|
|
func isPairing() -> Bool {
|
|
let pairingPath = PairingFileStore.prepareURL().path
|
|
var pairingFile: RpPairingFileHandle?
|
|
let error = rp_pairing_file_read(pairingPath, &pairingFile)
|
|
if error != nil {
|
|
return false
|
|
}
|
|
rp_pairing_file_free(pairingFile)
|
|
return true
|
|
}
|