mirror of
https://github.com/Lakr233/vphone-cli.git
synced 2026-10-01 23:54:35 +08:00
Show the iOS version and guest address as the window subtitle
Once vphoned connects, the VM window's subtitle reads `iOS <version> - <address>`, and it is empty while vphoned is away. vphoned's health report took the first en* address, which sorts to en0's fe80:: link-local address. It now picks a 192.x IPv4 address first, then any other IPv4 that is not loopback or 169.254, then a routable IPv6. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -40,10 +40,19 @@ enum GuestAPI {
|
||||
SHA256.hash(data: data).map { String(format: "%02x", $0) }.joined()
|
||||
}
|
||||
|
||||
/// The address the host shows for the guest, from icli's
|
||||
/// `"<interface> <address>"` strings: a 192.x IPv4 address (the NAT
|
||||
/// network), then any other routable IPv4, then a routable IPv6. Loopback
|
||||
/// and link-local addresses, which sort first, never qualify.
|
||||
static func preferredAddress(_ addresses: [String]) -> String? {
|
||||
let hosts = addresses.compactMap { $0.split(separator: " ", maxSplits: 1).last.map(String.init) }
|
||||
let ipv4 = hosts.filter { !$0.contains(":") && !$0.hasPrefix("127.") && !$0.hasPrefix("169.254.") }
|
||||
let ipv6 = hosts.filter { $0.contains(":") && $0 != "::1" && !$0.contains("%") && !$0.hasPrefix("fe80:") }
|
||||
return ipv4.first { $0.hasPrefix("192.") } ?? ipv4.first ?? ipv6.first
|
||||
}
|
||||
|
||||
static func health() -> [String: Any] {
|
||||
let addresses = networkInfo()["addresses"] as? [String] ?? []
|
||||
let ip = addresses.first(where: { $0.hasPrefix("en") && !$0.contains("127.0.0.1") })?
|
||||
.split(separator: " ").last.map(String.init)
|
||||
let ip = preferredAddress(networkInfo()["addresses"] as? [String] ?? [])
|
||||
let version = ProcessInfo.processInfo.operatingSystemVersion
|
||||
return [
|
||||
"name": "vphoned",
|
||||
|
||||
+19
-1
@@ -99,15 +99,33 @@ class VPhoneVirtualMachineWindowController: NSObject {
|
||||
monitor.start(control: control, window: window)
|
||||
touchIDMonitor = monitor
|
||||
|
||||
// Poll vphoned status for the Home button
|
||||
// Poll vphoned status for the Home button and the subtitle
|
||||
_ = Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { [weak self] _ in
|
||||
Task { @MainActor in
|
||||
guard let self, let control = self.control else { return }
|
||||
self.updateHomeButton(connected: control.isConnected)
|
||||
self.updateSubtitle(control: control)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Subtitle
|
||||
|
||||
/// `iOS <version> - <address>` from vphoned's health report, which picks
|
||||
/// the IPv4 address first and falls back to IPv6; empty until it connects.
|
||||
private func updateSubtitle(control: VPhoneGuestControl) {
|
||||
guard let window = windowController?.window else { return }
|
||||
var parts: [String] = []
|
||||
if control.isConnected {
|
||||
if let version = control.guestIOSVersion, !version.isEmpty { parts.append("iOS \(version)") }
|
||||
if let address = control.guestIPAddress, !address.isEmpty { parts.append(address) }
|
||||
}
|
||||
let subtitle = parts.joined(separator: " - ")
|
||||
if window.subtitle != subtitle {
|
||||
window.subtitle = subtitle
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Home Button
|
||||
|
||||
private static let homeImage = NSImage(
|
||||
|
||||
Reference in New Issue
Block a user