@@ -111,6 +111,15 @@ function buildAuthenticatedAssetUrl(path: string, stamp: number): string {
111111 return url . toString ( ) ;
112112}
113113
114+ function shouldUseRemoteStreamDefault ( apiRoot : string ) : boolean {
115+ if ( apiRoot ) {
116+ return true ;
117+ }
118+ return (
119+ new URLSearchParams ( window . location . search ) . get ( "remoteStream" ) === "1"
120+ ) ;
121+ }
122+
114123function shouldRenderNativeChrome ( simulator : SimulatorMetadata ) : boolean {
115124 const identifier = simulator . deviceTypeIdentifier ?? "" ;
116125 const name = simulator . name ?? "" ;
@@ -177,13 +186,15 @@ export interface AppShellProps {
177186 fixedSimulatorUDID ?: string | null ;
178187 hideSimulatorSelection ?: boolean ;
179188 pairingEnabled ?: boolean ;
189+ remoteStream ?: boolean ;
180190}
181191
182192export function AppShell ( {
183193 apiRoot = "" ,
184194 fixedSimulatorUDID = null ,
185195 hideSimulatorSelection = false ,
186196 pairingEnabled = true ,
197+ remoteStream = shouldUseRemoteStreamDefault ( apiRoot ) ,
187198} : AppShellProps = { } ) {
188199 configureSimDeckClient ( { apiRoot } ) ;
189200 const [ initialUiState ] = useState ( readPersistedUiState ) ;
@@ -201,7 +212,7 @@ export function AppShell({
201212 isLoading,
202213 refresh,
203214 simulators,
204- } = useSimulatorList ( ) ;
215+ } = useSimulatorList ( { remote : remoteStream } ) ;
205216 const [ debugVisible , setDebugVisible ] = useState ( false ) ;
206217 const [ hierarchyVisible , setHierarchyVisible ] = useState ( ( ) =>
207218 readStoredFlag ( HIERARCHY_VISIBLE_STORAGE_KEY ) ,
@@ -370,6 +381,7 @@ export function AppShell({
370381 streamCanvasKey,
371382 } = useLiveStream ( {
372383 canvasElement : streamCanvasElement ,
384+ remote : remoteStream ,
373385 simulator : selectedSimulator ,
374386 } ) ;
375387
@@ -843,9 +855,13 @@ export function AppShell({
843855 pairingEnabled &&
844856 listError === AUTH_REQUIRED_MESSAGE &&
845857 ! accessTokenFromLocation ( ) ;
858+ const visibleListError =
859+ remoteStream && hasFrame && listError === "Failed to fetch"
860+ ? ""
861+ : listError ;
846862 const error = pairingRequired
847863 ? localError || streamError
848- : localError || streamError || listError ;
864+ : localError || streamError || visibleListError ;
849865 const deviceTransform = `translate(${ pan . x } px, ${ pan . y + autoViewportOffsetY } px) scale(${ effectiveZoom } )` ;
850866 const chromeScreenRect = computeChromeScreenRect (
851867 viewportChromeProfile ,
@@ -979,18 +995,19 @@ export function AppShell({
979995 return state ;
980996 } , [ ] ) ;
981997
982- function sendControl ( udid : string , message : ControlMessage ) {
998+ function sendControl ( udid : string , message : ControlMessage ) : boolean {
983999 setLocalError ( "" ) ;
9841000 const encoded = JSON . stringify ( message ) ;
9851001 if ( sendWebRtcControlMessage ( encoded ) ) {
986- return ;
1002+ return true ;
9871003 }
9881004 const state = ensureControlSocket ( udid ) ;
9891005 if ( state . socket . readyState === WebSocket . OPEN ) {
9901006 state . socket . send ( encoded ) ;
9911007 } else {
9921008 state . pending . push ( encoded ) ;
9931009 }
1010+ return true ;
9941011 }
9951012
9961013 useEffect ( ( ) => closeControlSocket , [ closeControlSocket ] ) ;
@@ -1281,28 +1298,47 @@ export function AppShell({
12811298 if ( ! selectedSimulator ) {
12821299 return ;
12831300 }
1284- void runAction ( ( ) => dismissKeyboard ( selectedSimulator . udid ) , false ) ;
1301+ if (
1302+ ! sendControl ( selectedSimulator . udid , { type : "dismissKeyboard" } )
1303+ ) {
1304+ void runAction (
1305+ ( ) => dismissKeyboard ( selectedSimulator . udid ) ,
1306+ false ,
1307+ ) ;
1308+ }
12851309 } }
12861310 onHome = { ( ) => {
12871311 if ( ! selectedSimulator ) {
12881312 return ;
12891313 }
12901314 setAccessibilitySelectedId ( "" ) ;
12911315 setAccessibilityHoveredId ( null ) ;
1292- void runAction ( ( ) => pressHome ( selectedSimulator . udid ) , false ) ;
1316+ if ( ! sendControl ( selectedSimulator . udid , { type : "home" } ) ) {
1317+ void runAction ( ( ) => pressHome ( selectedSimulator . udid ) , false ) ;
1318+ }
12931319 } }
12941320 onOpenAppSwitcher = { ( ) => {
12951321 if ( ! selectedSimulator ) {
12961322 return ;
12971323 }
12981324 setAccessibilitySelectedId ( "" ) ;
12991325 setAccessibilityHoveredId ( null ) ;
1300- void runAction ( ( ) => openAppSwitcher ( selectedSimulator . udid ) , false ) ;
1326+ if ( ! sendControl ( selectedSimulator . udid , { type : "appSwitcher" } ) ) {
1327+ void runAction (
1328+ ( ) => openAppSwitcher ( selectedSimulator . udid ) ,
1329+ false ,
1330+ ) ;
1331+ }
13011332 } }
13021333 onRotateLeft = { ( ) => {
13031334 if ( ! selectedSimulator ) {
13041335 return ;
13051336 }
1337+ if ( sendControl ( selectedSimulator . udid , { type : "rotateLeft" } ) ) {
1338+ setRotationQuarterTurns ( ( current ) => ( current + 3 ) % 4 ) ;
1339+ setStreamStamp ( Date . now ( ) ) ;
1340+ return ;
1341+ }
13061342 void runAction ( async ( ) => {
13071343 await rotateLeft ( selectedSimulator . udid ) ;
13081344 setRotationQuarterTurns ( ( current ) => ( current + 3 ) % 4 ) ;
@@ -1315,6 +1351,11 @@ export function AppShell({
13151351 if ( ! selectedSimulator ) {
13161352 return ;
13171353 }
1354+ if ( sendControl ( selectedSimulator . udid , { type : "rotateRight" } ) ) {
1355+ setRotationQuarterTurns ( ( current ) => ( current + 1 ) % 4 ) ;
1356+ setStreamStamp ( Date . now ( ) ) ;
1357+ return ;
1358+ }
13181359 void runAction ( async ( ) => {
13191360 await rotateRight ( selectedSimulator . udid ) ;
13201361 setRotationQuarterTurns ( ( current ) => ( current + 1 ) % 4 ) ;
@@ -1339,7 +1380,10 @@ export function AppShell({
13391380 if ( ! selectedSimulator ) {
13401381 return ;
13411382 }
1342- void runAction ( ( ) => toggleAppearance ( selectedSimulator . udid ) ) ;
1383+ const encoded = JSON . stringify ( { type : "toggleAppearance" } ) ;
1384+ if ( ! sendWebRtcControlMessage ( encoded ) ) {
1385+ void runAction ( ( ) => toggleAppearance ( selectedSimulator . udid ) ) ;
1386+ }
13431387 } }
13441388 onToggleDebug = { ( ) => setDebugVisible ( ( current ) => ! current ) }
13451389 onToggleHierarchy = { ( ) => {
0 commit comments