Skip to content

Commit ef66239

Browse files
committed
fix: improve pairing and server auto-connect
1 parent f3e8aa4 commit ef66239

2 files changed

Lines changed: 61 additions & 11 deletions

File tree

ios/SimDeckStudio/App/AppModel.swift

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ final class AppModel {
152152
presentPairingOnAuth: false
153153
)
154154
isAutoConnecting = false
155-
hasAutoConnected = connected
155+
if connected {
156+
hasAutoConnected = true
157+
} else {
158+
await autoConnectToAvailableEndpointIfNeeded()
159+
}
156160
}
157161
}
158162
discovery.start()
@@ -762,24 +766,45 @@ final class AppModel {
762766
}
763767

764768
private func autoConnectIfNeeded(_ endpoint: SimDeckEndpoint) async {
765-
let connectionEndpoint = endpointWithReusableToken(endpoint)
766-
guard !connectionEndpoint.requiresPairing || connectionEndpoint.token?.nilIfBlank != nil else {
767-
return
768-
}
769769
guard !hasAutoConnected, !isAutoConnecting, self.endpoint == nil, authEndpoint == nil else { return }
770+
await autoConnectToAvailableEndpointIfNeeded(preferredEndpoint: endpoint)
771+
}
772+
773+
private func autoConnectToAvailableEndpointIfNeeded(preferredEndpoint: SimDeckEndpoint? = nil) async {
774+
guard !hasAutoConnected, !isAutoConnecting, self.endpoint == nil, authEndpoint == nil else { return }
775+
let candidates = autoConnectCandidates(preferredEndpoint: preferredEndpoint)
776+
guard !candidates.isEmpty else { return }
777+
770778
isAutoConnecting = true
771-
let connected = await connect(
772-
connectionEndpoint,
773-
autoStart: false,
774-
saveEndpoint: false,
775-
presentPairingOnAuth: false
776-
)
779+
var connected = false
780+
for candidate in candidates {
781+
connected = await connect(
782+
candidate,
783+
autoStart: false,
784+
saveEndpoint: false,
785+
presentPairingOnAuth: false
786+
)
787+
if connected {
788+
break
789+
}
790+
}
777791
isAutoConnecting = false
778792
if connected {
779793
hasAutoConnected = true
780794
}
781795
}
782796

797+
private func autoConnectCandidates(preferredEndpoint: SimDeckEndpoint?) -> [SimDeckEndpoint] {
798+
let orderedEndpoints = [preferredEndpoint].compactMap(\.self)
799+
+ discovery.endpoints
800+
+ savedEndpoints
801+
return uniqued(orderedEndpoints)
802+
.map(endpointWithReusableToken)
803+
.filter { endpoint in
804+
!endpoint.requiresPairing || endpoint.token?.nilIfBlank != nil
805+
}
806+
}
807+
783808
private func isCurrentStreamRequest(_ generation: Int, simulatorID: String) -> Bool {
784809
streamRequestGeneration == generation && selectedSimulatorID == simulatorID
785810
}

server/src/main.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,10 @@ fn render_qr_code(value: &str) -> anyhow::Result<String> {
14901490
.build())
14911491
}
14921492

1493+
fn print_pair_progress(message: impl AsRef<str>) {
1494+
eprintln!("simdeck pair: {}", message.as_ref());
1495+
}
1496+
14931497
fn wait_for_daemon(metadata: &DaemonMetadata, timeout: Duration) -> anyhow::Result<()> {
14941498
let deadline = Instant::now() + timeout;
14951499
while Instant::now() < deadline {
@@ -1749,15 +1753,28 @@ fn pair_global_service(options: PairGlobalServiceOptions) -> anyhow::Result<()>
17491753
json,
17501754
} = options;
17511755

1756+
if port.is_none() {
1757+
print_pair_progress("checking the installed service port");
1758+
}
17521759
let port = match port {
17531760
Some(port) => port,
17541761
None => service::installed_port()?.unwrap_or(choose_daemon_port_for_bind(4310, bind)?),
17551762
};
1763+
print_pair_progress(format!("using port {port}"));
1764+
1765+
print_pair_progress("detecting LAN and Tailscale addresses");
17561766
let advertise_host = advertise_host.or_else(|| {
17571767
detect_lan_ip()
17581768
.or_else(detect_tailscale_ip)
17591769
.map(|ip| ip.to_string())
17601770
});
1771+
if let Some(host) = advertise_host.as_deref() {
1772+
print_pair_progress(format!("advertising {host}:{port}"));
1773+
} else {
1774+
print_pair_progress("no LAN or Tailscale address detected; local pairing only");
1775+
}
1776+
1777+
print_pair_progress("starting the global SimDeck service");
17611778
let result = service::pair(ServiceOptions {
17621779
port,
17631780
bind,
@@ -1770,8 +1787,16 @@ fn pair_global_service(options: PairGlobalServiceOptions) -> anyhow::Result<()>
17701787
access_token: None,
17711788
pairing_code: None,
17721789
})?;
1790+
print_pair_progress(format!(
1791+
"installed {}; logs: {}, {}",
1792+
result.service,
1793+
result.stdout_log.display(),
1794+
result.stderr_log.display()
1795+
));
17731796
let target = PairingTarget::from_service(result)?;
1797+
print_pair_progress(format!("waiting for service health at {}", target.http_url));
17741798
wait_for_pairing_target(&target, Duration::from_secs(15))?;
1799+
print_pair_progress("service is ready; rendering pairing QR");
17751800
print_pairing_result(&target, true, json)
17761801
}
17771802

0 commit comments

Comments
 (0)