diff --git a/common/models/models.go b/common/models/models.go index b87dfa3..2455589 100644 --- a/common/models/models.go +++ b/common/models/models.go @@ -56,7 +56,8 @@ type Device struct { ProviderState string `json:"provider_state" bson:"-"` // current state of the device on the provider - init, preparing, live /// PROVIDER ONLY VALUES //// RETURNABLE VALUES - InstalledApps []string `json:"installed_apps" bson:"-"` // list of installed apps on device + InstalledApps []string `json:"installed_apps" bson:"-"` // list of installed apps on device + UsesCustomWDA bool `json:"uses_custom_wda" bson:"-"` // Flag for iOS device if provider sets up custom WDA ///// NON-RETURNABLE VALUES AppiumSessionID string `json:"-" bson:"-"` // current Appium session ID WDASessionID string `json:"-" bson:"-"` // current WebDriverAgent session ID diff --git a/hub/gads-ui/src/components/DeviceControl/StreamCanvas.js b/hub/gads-ui/src/components/DeviceControl/StreamCanvas.js index 6640829..09dbe67 100644 --- a/hub/gads-ui/src/components/DeviceControl/StreamCanvas.js +++ b/hub/gads-ui/src/components/DeviceControl/StreamCanvas.js @@ -1,7 +1,7 @@ import { Auth } from "../../contexts/Auth" import { useContext, useEffect, useState } from "react" import './StreamCanvas.css' -import { Button, Divider, Grid, Stack } from "@mui/material" +import { Button, Divider, Grid, Stack, Tooltip } from "@mui/material" import HomeIcon from '@mui/icons-material/Home'; import LockOpenIcon from '@mui/icons-material/LockOpen'; import LockIcon from '@mui/icons-material/Lock'; @@ -15,10 +15,15 @@ export default function StreamCanvas({ deviceData }) { width: 0, height: 0 }); + const [isPortrait, setIsPortrait] = useState(true) + const handleOrientationButtonClick = (isPortrait) => { + setIsPortrait(isPortrait); + } let deviceX = parseInt(deviceData.screen_width, 10) let deviceY = parseInt(deviceData.screen_height, 10) let screen_ratio = deviceX / deviceY + let landscapeScreenRatio = deviceY / deviceX const streamData = { udid: deviceData.udid, @@ -26,22 +31,31 @@ export default function StreamCanvas({ deviceData }) { deviceY: deviceY, screen_ratio: screen_ratio, canvasHeight: canvasSize.height, - canvasWidth: canvasSize.width + canvasWidth: canvasSize.width, + isPortrait: isPortrait, + device_os: deviceData.os, + uses_custom_wda: deviceData.uses_custom_wda } let streamUrl = "" if (deviceData.os === 'ios') { - // streamUrl = `http://192.168.68.109:10000/device/${deviceData.udid}/ios-stream-mjpeg` + // streamUrl = `http://192.168.1.6:10000/device/${deviceData.udid}/ios-stream-mjpeg` streamUrl = `/device/${deviceData.udid}/ios-stream-mjpeg` } else { - // streamUrl = `http://192.168.68.109:10000/device/${deviceData.udid}/android-stream-mjpeg` + // streamUrl = `http://192.168.1.6:10000/device/${deviceData.udid}/android-stream-mjpeg` streamUrl = `/device/${deviceData.udid}/android-stream-mjpeg` } useEffect(() => { const updateCanvasSize = () => { - let canvasHeight = window.innerHeight * 0.7 - let canvasWidth = canvasHeight * screen_ratio + let canvasWidth, canvasHeight + if (isPortrait) { + canvasHeight = window.innerHeight * 0.7 + canvasWidth = canvasHeight * screen_ratio + } else { + canvasWidth = window.innerWidth * 0.4 + canvasHeight = canvasWidth / landscapeScreenRatio + } setCanvasSize({ width: canvasWidth, @@ -49,8 +63,16 @@ export default function StreamCanvas({ deviceData }) { }) } + const imgElement = document.getElementById('image-stream'); + + // Temporarily remove the stream source + imgElement.src = ''; + updateCanvasSize() + // Reapply the stream URL after the resize is complete + imgElement.src = streamUrl; + // Set resize listener window.addEventListener('resize', updateCanvasSize); @@ -58,88 +80,119 @@ export default function StreamCanvas({ deviceData }) { window.stop() window.removeEventListener('resize', updateCanvasSize); } - }, []); + }, [isPortrait]); return ( -
-

{deviceData.model}

+
- - -
- - - - -
+ + Unlock - - - + > + + + + + + + + + + + + ) } @@ -150,9 +203,28 @@ function Canvas({ authToken, logout, streamData, setDialog }) { function getCursorCoordinates(event) { const rect = event.currentTarget.getBoundingClientRect() - const x = event.clientX - rect.left - const y = event.clientY - rect.top - return [x, y]; + // If its portrait use the usual calculation for tap coordinates + if (streamData.isPortrait) { + const x = event.clientX - rect.left + const y = event.clientY - rect.top + return [x, y] + } + // If its landscape and the provider uses custom wda for tapping/swiping + if (streamData.device_os === 'ios' && streamData.uses_custom_wda) { + // Have to subtract the tap coordinate from the canvas height + // Because the custom wda tap uses coordinates where in landscape + // x starts from the bottom(being essentially reversed y) + // and y starts from the left(being essentially x) + const x = streamData.canvasHeight - (event.clientY - rect.top) + const y = event.clientX - rect.left + return [x, y] + } + // If its landscape and provider does not use custom wda for tapping/swiping + // just reverse x and y + const x = event.clientY - rect.top + const y = event.clientX - rect.left + console.log("Returning " + x + " " + y) + return [y, x]; } function handleMouseDown(event) { @@ -218,8 +290,13 @@ function tapCoordinates(authToken, logout, pos, streamData, setDialog) { // if the stream height if (streamData.canvasHeight != streamData.deviceY) { - x = (x / streamData.canvasWidth) * streamData.deviceX - y = (y / streamData.canvasHeight) * streamData.deviceY + if (streamData.isPortrait) { + x = (x / streamData.canvasWidth) * streamData.deviceX + y = (y / streamData.canvasHeight) * streamData.deviceY + } else { + x = (x / streamData.canvasHeight) * streamData.deviceX + y = (y / streamData.canvasWidth) * streamData.deviceY + } } let jsonData = JSON.stringify({ @@ -287,10 +364,22 @@ function swipeCoordinates(authToken, logout, coord1, coord2, streamData, setDial // if the stream height if (streamData.canvasHeight != streamData.deviceY) { - firstCoordX = (firstCoordX / streamData.canvasWidth) * streamData.deviceX - firstCoordY = (firstCoordY / streamData.canvasHeight) * streamData.deviceY - secondCoordX = (secondCoordX / streamData.canvasWidth) * streamData.deviceX - secondCoordY = (secondCoordY / streamData.canvasHeight) * streamData.deviceY + // If the device is landscape and is android + // We need to switch the coordinate calculation + // Divide by height for X and divide by width for Y + if (streamData.device_os === 'android' && !streamData.isPortrait) { + firstCoordX = (firstCoordX / streamData.canvasHeight) * streamData.deviceX + firstCoordY = (firstCoordY / streamData.canvasWidth) * streamData.deviceY + secondCoordX = (secondCoordX / streamData.canvasHeight) * streamData.deviceX + secondCoordY = (secondCoordY / streamData.canvasWidth) * streamData.deviceY + } else { + // If the device is not in landscape and is not android + // Divide as usual - X by width and Y by height + firstCoordX = (firstCoordX / streamData.canvasWidth) * streamData.deviceX + firstCoordY = (firstCoordY / streamData.canvasHeight) * streamData.deviceY + secondCoordX = (secondCoordX / streamData.canvasWidth) * streamData.deviceX + secondCoordY = (secondCoordY / streamData.canvasHeight) * streamData.deviceY + } } let jsonData = JSON.stringify({ diff --git a/provider/router/routes.go b/provider/router/routes.go index b3a788d..86d20ee 100644 --- a/provider/router/routes.go +++ b/provider/router/routes.go @@ -238,6 +238,7 @@ func DeviceInfo(c *gin.Context) { if dev, ok := devices.DBDeviceMap[udid]; ok { devices.UpdateInstalledApps(dev) + dev.UsesCustomWDA = config.ProviderConfig.UseCustomWDA c.JSON(http.StatusOK, dev) return }