Skip to content

Commit b08ec08

Browse files
committed
fix: route live simulator input over realtime channels
1 parent a7e3fc1 commit b08ec08

7 files changed

Lines changed: 344 additions & 194 deletions

File tree

client/src/api/controls.ts

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,7 @@ export type ControlMessage =
3131
async function postSimulatorAction(
3232
udid: string,
3333
action: string,
34-
payload?:
35-
| ButtonPayload
36-
| CrownPayload
37-
| KeyPayload
38-
| LaunchPayload
39-
| OpenUrlPayload
40-
| TouchPayload,
34+
payload?: LaunchPayload | OpenUrlPayload,
4135
): Promise<SimulatorMetadata | null> {
4236
const response = await apiRequest<SimulatorResponse | { ok: boolean }>(
4337
`/api/simulators/${udid}/${action}`,
@@ -58,10 +52,6 @@ export function shutdownSimulator(udid: string) {
5852
return postSimulatorAction(udid, "shutdown");
5953
}
6054

61-
export function toggleAppearance(udid: string) {
62-
return postSimulatorAction(udid, "toggle-appearance");
63-
}
64-
6555
export function openSimulatorUrl(udid: string, payload: OpenUrlPayload) {
6656
return postSimulatorAction(udid, "open-url", payload);
6757
}
@@ -87,14 +77,6 @@ export function uploadSimulatorApp(
8777
);
8878
}
8979

90-
export function sendTouch(udid: string, payload: TouchPayload) {
91-
return postSimulatorAction(udid, "touch", payload);
92-
}
93-
94-
export function sendKey(udid: string, payload: KeyPayload) {
95-
return postSimulatorAction(udid, "key", payload);
96-
}
97-
9880
export function simulatorControlSocketUrl(udid: string) {
9981
const url = new URL(
10082
apiUrl(`/api/simulators/${encodeURIComponent(udid)}/control`),
@@ -108,34 +90,6 @@ export function simulatorControlSocketUrl(udid: string) {
10890
return url.toString();
10991
}
11092

111-
export function dismissKeyboard(udid: string) {
112-
return postSimulatorAction(udid, "dismiss-keyboard");
113-
}
114-
115-
export function pressHome(udid: string) {
116-
return postSimulatorAction(udid, "home");
117-
}
118-
119-
export function pressSimulatorButton(udid: string, payload: ButtonPayload) {
120-
return postSimulatorAction(udid, "button", payload);
121-
}
122-
123-
export function rotateDigitalCrown(udid: string, payload: CrownPayload) {
124-
return postSimulatorAction(udid, "crown", payload);
125-
}
126-
127-
export function openAppSwitcher(udid: string) {
128-
return postSimulatorAction(udid, "app-switcher");
129-
}
130-
131-
export function rotateLeft(udid: string) {
132-
return postSimulatorAction(udid, "rotate-left");
133-
}
134-
135-
export function rotateRight(udid: string) {
136-
return postSimulatorAction(udid, "rotate-right");
137-
}
138-
13993
async function fetchSimulatorBlob(
14094
path: string,
14195
options: RequestInit = {},

client/src/app/AppShell.tsx

Lines changed: 39 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,11 @@ import { apiUrl, configureSimDeckClient } from "../api/config";
1818
import {
1919
bootSimulator,
2020
captureSimulatorScreenshot,
21-
dismissKeyboard,
2221
launchSimulatorBundle,
23-
openAppSwitcher,
2422
openSimulatorUrl,
25-
pressHome,
26-
pressSimulatorButton,
2723
recordSimulatorScreen,
28-
rotateDigitalCrown,
29-
rotateRight,
3024
simulatorControlSocketUrl,
3125
shutdownSimulator,
32-
toggleAppearance,
3326
uploadSimulatorApp,
3427
type ControlMessage,
3528
} from "../api/controls";
@@ -2057,6 +2050,19 @@ export function AppShell({
20572050
return state;
20582051
}, []);
20592052

2053+
useEffect(() => {
2054+
if (!selectedSimulator?.isBooted) {
2055+
closeControlSocket();
2056+
return;
2057+
}
2058+
ensureControlSocket(selectedSimulator.udid);
2059+
}, [
2060+
closeControlSocket,
2061+
ensureControlSocket,
2062+
selectedSimulator?.isBooted,
2063+
selectedSimulator?.udid,
2064+
]);
2065+
20602066
function sendControl(udid: string, message: ControlMessage): boolean {
20612067
if (isMoveControlMessage(message)) {
20622068
pendingControlMoveRef.current = { message, udid };
@@ -2096,9 +2102,20 @@ export function AppShell({
20962102
if (sendWebRtcControlMessage(encoded, { dropIfBacklogged })) {
20972103
return true;
20982104
}
2105+
if (sendControlSocketMessage(udid, encoded, dropIfBacklogged)) {
2106+
return true;
2107+
}
20992108
if (remoteStream) {
21002109
return false;
21012110
}
2111+
return false;
2112+
}
2113+
2114+
function sendControlSocketMessage(
2115+
udid: string,
2116+
encoded: string,
2117+
dropIfBacklogged: boolean,
2118+
): boolean {
21022119
const state = ensureControlSocket(udid);
21032120
if (state.socket.readyState === WebSocket.OPEN) {
21042121
if (
@@ -2405,16 +2422,7 @@ export function AppShell({
24052422
usage,
24062423
})
24072424
) {
2408-
void runAction(
2409-
() =>
2410-
pressSimulatorButton(selectedSimulator.udid, {
2411-
button,
2412-
phase,
2413-
usagePage,
2414-
usage,
2415-
}),
2416-
false,
2417-
);
2425+
setLocalError("Simulator control stream disconnected.");
24182426
}
24192427
}
24202428

@@ -2430,10 +2438,7 @@ export function AppShell({
24302438
delta,
24312439
})
24322440
) {
2433-
void runAction(
2434-
() => rotateDigitalCrown(selectedSimulator.udid, { delta }),
2435-
false,
2436-
);
2441+
setLocalError("Simulator control stream disconnected.");
24372442
}
24382443
}
24392444

@@ -2703,10 +2708,7 @@ export function AppShell({
27032708
if (
27042709
!sendControl(selectedSimulator.udid, { type: "dismissKeyboard" })
27052710
) {
2706-
void runAction(
2707-
() => dismissKeyboard(selectedSimulator.udid),
2708-
false,
2709-
);
2711+
setLocalError("Simulator control stream disconnected.");
27102712
}
27112713
}}
27122714
onHome={() => {
@@ -2716,7 +2718,7 @@ export function AppShell({
27162718
setAccessibilitySelectedId("");
27172719
setAccessibilityHoveredId(null);
27182720
if (!sendControl(selectedSimulator.udid, { type: "home" })) {
2719-
void runAction(() => pressHome(selectedSimulator.udid), false);
2721+
setLocalError("Simulator control stream disconnected.");
27202722
}
27212723
}}
27222724
onInstallAppPrompt={openInstallAppPicker}
@@ -2727,10 +2729,7 @@ export function AppShell({
27272729
setAccessibilitySelectedId("");
27282730
setAccessibilityHoveredId(null);
27292731
if (!sendControl(selectedSimulator.udid, { type: "appSwitcher" })) {
2730-
void runAction(
2731-
() => openAppSwitcher(selectedSimulator.udid),
2732-
false,
2733-
);
2732+
setLocalError("Simulator control stream disconnected.");
27342733
}
27352734
}}
27362735
onOpenBundlePrompt={promptForBundleID}
@@ -2748,23 +2747,18 @@ export function AppShell({
27482747
}
27492748
const androidViewport = isAndroidSimulator(selectedSimulator);
27502749
beginZoomAnimation();
2751-
if (androidViewport) {
2752-
void runAction(async () => {
2753-
await rotateRight(selectedSimulator.udid);
2754-
setRotationQuarterTurns(0);
2755-
beginZoomAnimation();
2756-
await refresh();
2757-
}, false);
2758-
return;
2759-
}
27602750
if (sendControl(selectedSimulator.udid, { type: "rotateRight" })) {
2761-
setRotationQuarterTurns((current) => (current + 1) % 4);
2751+
if (androidViewport) {
2752+
setRotationQuarterTurns(0);
2753+
window.setTimeout(() => {
2754+
void refresh();
2755+
}, 250);
2756+
} else {
2757+
setRotationQuarterTurns((current) => (current + 1) % 4);
2758+
}
27622759
return;
27632760
}
2764-
void runAction(async () => {
2765-
await rotateRight(selectedSimulator.udid);
2766-
setRotationQuarterTurns((current) => (current + 1) % 4);
2767-
}, false);
2761+
setLocalError("Simulator control stream disconnected.");
27682762
}}
27692763
onRecordScreen={() => {
27702764
void downloadSimulatorRecording();
@@ -2789,10 +2783,7 @@ export function AppShell({
27892783
if (
27902784
!sendControl(selectedSimulator.udid, { type: "toggleAppearance" })
27912785
) {
2792-
void runAction(
2793-
() => toggleAppearance(selectedSimulator.udid),
2794-
false,
2795-
);
2786+
setLocalError("Simulator control stream disconnected.");
27962787
}
27972788
}}
27982789
onToggleDebug={() => setDebugVisible((current) => !current)}

ios/SimDeckStudio.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@
449449
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
450450
CODE_SIGN_ENTITLEMENTS = SimDeckStudio/SimDeckStudio.entitlements;
451451
CODE_SIGN_STYLE = Automatic;
452-
CURRENT_PROJECT_VERSION = 202605191259;
452+
CURRENT_PROJECT_VERSION = 20260519200323;
453453
DEVELOPMENT_ASSET_PATHS = "";
454454
DEVELOPMENT_TEAM = CS838V553Y;
455455
ENABLE_PREVIEWS = YES;
@@ -478,7 +478,7 @@
478478
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
479479
CODE_SIGN_ENTITLEMENTS = SimDeckStudio/SimDeckStudio.entitlements;
480480
CODE_SIGN_STYLE = Automatic;
481-
CURRENT_PROJECT_VERSION = 202605191259;
481+
CURRENT_PROJECT_VERSION = 20260519200323;
482482
DEVELOPMENT_ASSET_PATHS = "";
483483
DEVELOPMENT_TEAM = CS838V553Y;
484484
ENABLE_PREVIEWS = YES;

0 commit comments

Comments
 (0)