Skip to main content
Glama
InteractPageLayout.tsx4.48 kB
import React, { useState } from "react"; import clsx from "clsx"; import InteractableDevice from "../device-and-device-elements/InteractableDevice"; import ReplView from "../commands/ReplView"; import ActionModal from "../device-and-device-elements/ActionModal"; import { Button } from "../design-system/button"; import { CommandExample } from "../../helpers/commandExample"; import ElementsPanel from "../device-and-device-elements/ElementsPanel"; import DeviceWrapperAspectRatio from "../device-and-device-elements/DeviceWrapperAspectRatio"; import { useDeviceContext } from "../../context/DeviceContext"; import { Spinner } from "../design-system/spinner"; import { useRepl } from '../../context/ReplContext'; import { DeviceScreen } from "../../helpers/models"; import BrowserActionBar from "../device-and-device-elements/BrowserActionBar"; const InteractPageLayout = () => { const { isLoading, deviceScreen, footerHint, setInspectedElement, setCurrentCommandValue, } = useDeviceContext(); const { runCommandYaml } = useRepl(); const [showElementsPanel, setShowElementsPanel] = useState<boolean>(false); const [isUrlLoading, setIsUrlLoading] = useState<boolean>(false); const onEdit = (example: CommandExample) => { if (example.status === "unavailable") return; setCurrentCommandValue(example.content.trim()); setInspectedElement(null); // find textarea by id and focus on it if it exists setTimeout(() => { const textarea = document.getElementById("commandInputBox"); if (textarea) { textarea.focus(); } }, 0); }; const onRun = async (example: CommandExample) => { if (example.status === "unavailable") return; setInspectedElement(null); await runCommandYaml(example.content); }; const onUrlUpdated = (url: string) => { setIsUrlLoading(true); runCommandYaml(`openLink: ${url}`).finally(() => { // Wait some time to update the url from the device screen setTimeout(() => { setIsUrlLoading(false); }, 1000); }); } if (isLoading) return ( <div className="flex items-center justify-center h-full"> <Spinner size="32" /> </div> ); if (!deviceScreen) return null; var widthClass = computeWidthClass(deviceScreen, showElementsPanel); return ( <div className="flex h-full overflow-hidden"> {showElementsPanel && ( <ElementsPanel closePanel={() => setShowElementsPanel(false)} /> )} <div className={clsx( "px-8 pt-6 pb-7 bg-white dark:bg-slate-900 relative gap-4 flex flex-col", widthClass )} > {!showElementsPanel && ( <Button variant="secondary" leftIcon="RiSearchLine" className="w-full min-h-[32px]" onClick={() => setShowElementsPanel(true)} > Search Elements with Text or Id </Button> )} {deviceScreen?.platform === 'WEB' && ( <BrowserActionBar currentUrl={deviceScreen.url} onUrlUpdated={onUrlUpdated} isLoading={isUrlLoading} /> )} <DeviceWrapperAspectRatio> <InteractableDevice /> </DeviceWrapperAspectRatio> <p className="text-xs text-center"> Hold CMD (⌘) down to freely tap and swipe on the device screen </p> {footerHint && ( <div className="absolute bottom-0 left-0 right-0 text-xs text-center bg-slate-100 dark:bg-slate-800 dark:text-white h-auto text-slate-800 overflow-hidden"> {footerHint} </div> )} </div> <div className="flex flex-col flex-1 h-full overflow-hidden border-l border-slate-200 dark:border-slate-800 relative dark:bg-slate-900 dark:text-white"> <ReplView /> </div> <ActionModal onEdit={onEdit} onRun={onRun} /> </div> ); }; function computeWidthClass(deviceScreen: DeviceScreen, showElementsPanel: boolean) { const wideDevice = deviceScreen.width > deviceScreen.height; var widthModifier = "basis-1/2"; if (showElementsPanel) { widthModifier += " max-w-[33.333333%]"; if (wideDevice) { widthModifier += " lg:basis-5/12"; } } else { if (wideDevice) { widthModifier += " max-w-[80%]"; } else { widthModifier += " lg:basis-4/12 max-w-[41.666667%]"; } } return widthModifier; } export default InteractPageLayout;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mobile-dev-inc/Maestro'

If you have feedback or need assistance with the MCP directory API, please join our Discord server