diff --git a/packages/client/src/app/AppShell.tsx b/packages/client/src/app/AppShell.tsx index 3848b3a7..41ae71a5 100644 --- a/packages/client/src/app/AppShell.tsx +++ b/packages/client/src/app/AppShell.tsx @@ -2761,6 +2761,33 @@ export function AppShell({ }, 1800); } + function rotateSelectedSimulator(direction: "left" | "right") { + if (!selectedSimulator) { + return; + } + if (selectedHasFixedOrientation) { + return; + } + const androidViewport = isAndroidSimulator(selectedSimulator); + const controlType = direction === "left" ? "rotateLeft" : "rotateRight"; + const rotationDelta = direction === "left" ? -1 : 1; + beginZoomAnimation(); + if (sendControl(selectedSimulator.udid, { type: controlType })) { + if (androidViewport) { + setRotationQuarterTurns(0); + window.setTimeout(() => { + void refresh(); + }, 250); + } else { + setRotationQuarterTurns((current) => + normalizeQuarterTurns(current + rotationDelta), + ); + } + return; + } + setLocalError("Simulator control stream disconnected."); + } + async function submitPairing(event: FormEvent) { event.preventDefault(); const code = pairingCode.trim(); @@ -2889,28 +2916,8 @@ export function AppShell({ setNewSimulatorOpen(true); }} onOpenUrlPrompt={promptForURL} - onRotateRight={() => { - if (!selectedSimulator) { - return; - } - if (selectedHasFixedOrientation) { - return; - } - const androidViewport = isAndroidSimulator(selectedSimulator); - beginZoomAnimation(); - if (sendControl(selectedSimulator.udid, { type: "rotateRight" })) { - if (androidViewport) { - setRotationQuarterTurns(0); - window.setTimeout(() => { - void refresh(); - }, 250); - } else { - setRotationQuarterTurns((current) => (current + 1) % 4); - } - return; - } - setLocalError("Simulator control stream disconnected."); - }} + onRotateLeft={() => rotateSelectedSimulator("left")} + onRotateRight={() => rotateSelectedSimulator("right")} onToggleRecording={() => { void toggleSimulatorRecording(); }} diff --git a/packages/client/src/features/toolbar/Toolbar.tsx b/packages/client/src/features/toolbar/Toolbar.tsx index 7f7c63d6..6a5f3e94 100644 --- a/packages/client/src/features/toolbar/Toolbar.tsx +++ b/packages/client/src/features/toolbar/Toolbar.tsx @@ -6,7 +6,7 @@ import { LayersIcon as HierarchyIcon, Link2Icon as OpenUrlIcon, PlayIcon, - ReloadIcon as RotateRightIcon, + RotateCounterClockwiseIcon as RotateLeftIcon, StopIcon, } from "@radix-ui/react-icons"; import { useEffect, useState, type RefObject } from "react"; @@ -43,6 +43,7 @@ interface ToolbarProps { onOpenBundlePrompt: () => void; onOpenNewSimulator: () => void; onOpenUrlPrompt: () => void; + onRotateLeft: () => void; onRotateRight: () => void; onShutdown: () => void; onStreamEncoderChange: (encoder: StreamEncoder) => void; @@ -104,6 +105,7 @@ export function Toolbar({ onOpenBundlePrompt, onOpenNewSimulator, onOpenUrlPrompt, + onRotateLeft, onRotateRight, onShutdown, onStreamEncoderChange, @@ -279,14 +281,24 @@ export function Toolbar({ {canRotateSelectedSimulator ? ( - + <> + + + ) : null} ) : null} diff --git a/packages/client/src/styles/components.css b/packages/client/src/styles/components.css index 564b44ed..8f4dc308 100644 --- a/packages/client/src/styles/components.css +++ b/packages/client/src/styles/components.css @@ -117,6 +117,10 @@ height: 16px; } +.toolbar-right .icon-btn .rotate-right-icon { + transform: scaleX(-1); +} + .state-dot { width: 6px; height: 6px; diff --git a/packages/client/src/styles/layout.css b/packages/client/src/styles/layout.css index 02a53bf4..d5a2a8e7 100644 --- a/packages/client/src/styles/layout.css +++ b/packages/client/src/styles/layout.css @@ -128,6 +128,12 @@ min-width: 0; } +@media (max-width: 960px) { + .toolbar .toolbar-wide-hidden { + display: none; + } +} + .main { position: relative; display: flex;