feat(Device): add get screen size

This commit is contained in:
AkiChase 2024-04-30 09:57:47 +08:00
parent 6284648663
commit 14ac09a7ed
6 changed files with 121 additions and 60 deletions

View File

@ -58,6 +58,27 @@ impl Device {
.spawn()
.context("Failed to execute 'adb shell'")?)
}
/// execute "adb shell wm size" to get screen size
pub fn cmd_screen_size(res_dir: &PathBuf, id: &str) -> Result<(u32, u32)> {
let mut adb_command = Adb::cmd_base(res_dir);
let output = adb_command
.args(&["-s", id, "shell", "wm", "size"])
.output()
.context("Failed to execute 'adb shell wm size'")?;
for line in output.stdout.lines() {
if let std::result::Result::Ok(line) = line {
if line.starts_with("Physical size: ") {
let size_str = line.trim_start_matches("Physical size: ").split('x');
let width = size_str.clone().next().unwrap().parse::<u32>().unwrap();
let height = size_str.clone().last().unwrap().parse::<u32>().unwrap();
return Ok((width, height));
}
}
};
Err(anyhow::anyhow!("Failed to get screen size"))
}
}
pub struct Adb;

View File

@ -40,6 +40,11 @@ impl ScrcpyClient {
Adb::cmd_forward_remove(res_dir)
}
// get the screen size of the device
pub fn get_device_screen_size(res_dir: &PathBuf, id: &str) -> Result<(u32, u32)> {
Device::cmd_screen_size(res_dir, id)
}
/// push server file to current device
pub fn push_server_file(res_dir: &PathBuf, id: &str) -> Result<()> {
let info = Device::cmd_push(

View File

@ -108,6 +108,15 @@ fn start_scrcpy_server(
Ok(())
}
#[tauri::command]
fn get_device_screen_size(id: String, app: tauri::AppHandle) -> Result<(u32, u32), String> {
let dir = app.path().resource_dir().unwrap().join("resource");
match ScrcpyClient::get_device_screen_size(&dir, &id) {
Ok(size) => Ok(size),
Err(e) => Err(e.to_string()),
}
}
#[tauri::command]
fn load_default_keyconfig(app: tauri::AppHandle) -> Result<String, String> {
let dir = app.path().resource_dir().unwrap().join("resource");
@ -194,6 +203,7 @@ async fn main() {
forward_server_port,
push_server_file,
start_scrcpy_server,
get_device_screen_size,
load_default_keyconfig
])
.run(tauri::generate_context!())

View File

@ -15,6 +15,7 @@ import {
pushServerFile,
forwardServerPort,
startScrcpyServer,
getDeviceScreenSize,
} from "../invoke";
import {
NH4,
@ -160,74 +161,92 @@ const menuOptions: DropdownOption[] = [
label: () => h("span", "控制此设备"),
key: "control",
},
{
label: () => h("span", "获取屏幕尺寸"),
key: "screen",
},
];
function onMenuClickoutside() {
showMenu.value = false;
}
async function deviceControl() {
if (!port.value) {
port.value = 27183;
}
if (!(store.screenSizeW > 0) || !(store.screenSizeH > 0)) {
message.error("请正确输入当前控制设备的屏幕尺寸");
store.screenSizeW = 0;
store.screenSizeH = 0;
store.hideLoading();
return;
}
if (store.controledDevice) {
message.error("请先关闭当前控制设备");
store.hideLoading();
return;
}
localStore.set("screenSize", {
sizeW: store.screenSizeW,
sizeH: store.screenSizeH,
});
message.info("屏幕尺寸已保存,正在启动控制服务,请保持设备亮屏");
const device = devices.value[rowIndex];
let scid = (
"00000000" + Math.floor(Math.random() * 100000).toString(16)
).slice(-8);
await pushServerFile(device.id);
await forwardServerPort(device.id, scid, port.value);
await startScrcpyServer(device.id, scid, `127.0.0.1:${port.value}`);
// connection timeout check
let id = setTimeout(async () => {
if (deviceWaitForMetadataTask) {
await shutdown();
store.controledDevice = null;
store.hideLoading();
message.error("设备连接超时");
}
}, 6000);
// add cb for metadata
deviceWaitForMetadataTask = (deviceName: string) => {
store.controledDevice = {
scid,
deviceName,
device,
};
nextTick(() => {
deviceWaitForMetadataTask = null;
clearTimeout(id);
store.hideLoading();
});
};
}
async function deviceGetScreenSize() {
let id = devices.value[rowIndex].id;
const size = await getDeviceScreenSize(id);
store.hideLoading();
message.success(`设备屏幕尺寸为: ${size[0]} x ${size[1]}`);
}
async function onMenuSelect(key: string) {
showMenu.value = false;
store.showLoading();
switch (key) {
case "control":
if (!port.value) {
port.value = 27183;
}
if (!(store.screenSizeW > 0) || !(store.screenSizeH > 0)) {
message.error("请正确输入当前控制设备的屏幕尺寸");
store.screenSizeW = 0;
store.screenSizeH = 0;
store.hideLoading();
return;
}
if (store.controledDevice) {
message.error("请先关闭当前控制设备");
store.hideLoading();
return;
}
localStore.set("screenSize", {
sizeW: store.screenSizeW,
sizeH: store.screenSizeH,
});
message.info("屏幕尺寸已保存,正在启动控制服务,请保持设备亮屏");
let device = devices.value[rowIndex];
let scid = (
"00000000" + Math.floor(Math.random() * 100000).toString(16)
).slice(-8);
await pushServerFile(device.id);
await forwardServerPort(device.id, scid, port.value);
await startScrcpyServer(device.id, scid, `127.0.0.1:${port.value}`);
// connection timeout check
let id = setTimeout(async () => {
if (deviceWaitForMetadataTask) {
await shutdown();
store.controledDevice = null;
store.hideLoading();
message.error("设备连接超时");
}
}, 6000);
// add cb for metadata
deviceWaitForMetadataTask = (deviceName: string) => {
store.controledDevice = {
scid,
deviceName,
device,
};
nextTick(() => {
deviceWaitForMetadataTask = null;
clearTimeout(id);
store.hideLoading();
});
};
await deviceControl();
break;
case "screen":
await deviceGetScreenSize();
break;
}
}
@ -297,7 +316,7 @@ async function refreshDevices() {
</NButton>
</template>
scid: {{ store.controledDevice.scid }} <br />status:
{{ store.controledDevice.device.status }} <br />screen:
{{ store.controledDevice.device.status }}
</NTooltip>
<NButton quaternary circle type="error" @click="shutdownSC()">
<template #icon>

View File

@ -1,4 +1,4 @@
import { invoke } from '@tauri-apps/api/core';
import { invoke } from "@tauri-apps/api/core";
interface Device {
id: string;
@ -29,6 +29,12 @@ export async function startScrcpyServer(
return await invoke("start_scrcpy_server", { id, scid, address });
}
export async function getDeviceScreenSize(
id: string
): Promise<[number, number]> {
return await invoke("get_device_screen_size", { id });
}
export async function loadDefaultKeyconfig(): Promise<string> {
return await invoke("load_default_keyconfig");
}

View File

@ -5,7 +5,7 @@ import KeyBoard from "./components/keyboard/KeyBoard.vue";
import Device from "./components/Device.vue";
const routes = [
{ path: "/mask", name: "mask", component: Mask },
{ path: "/", name: "mask", component: Mask },
{ path: "/device", name: "device", component: Device },
{ path: "/setting", name: "setting", component: Setting },
{ path: "/keyboard", name: "keyboard", component: KeyBoard },