feat(adb): add adb path setting

This commit is contained in:
AkiChase 2024-05-22 09:03:44 +08:00
parent 7fc1ad1e3f
commit 4bf36cbdfa
10 changed files with 113 additions and 13 deletions

View File

@ -8,6 +8,8 @@ use std::os::windows::process::CommandExt;
use anyhow::{Context, Ok, Result};
use crate::share;
#[derive(Clone, Debug, serde::Serialize)]
pub struct Device {
pub id: String,
@ -85,13 +87,14 @@ pub struct Adb;
/// But some output of command won't be output, like adb service startup information.
impl Adb {
pub fn cmd_base() -> Command {
let adb_path = share::ADB_PATH.lock().unwrap().clone();
#[cfg(target_os = "windows")]
{
let mut cmd = Command::new("adb");
let mut cmd = Command::new(adb_path);
cmd.creation_flags(0x08000000); // CREATE_NO_WINDOW
return cmd;
}
Command::new("adb")
Command::new(adb_path)
}
/// execute "adb devices" and return devices list

View File

@ -157,6 +157,24 @@ fn check_adb_available() -> Result<(), String> {
}
}
#[tauri::command]
fn set_adb_path(adb_path: String, app: tauri::AppHandle) -> Result<(), String> {
let app_h = app.app_handle().clone();
let stores = app_h.state::<tauri_plugin_store::StoreCollection<tauri::Wry>>();
let path = std::path::PathBuf::from("store.bin");
let store_res: Result<(), tauri_plugin_store::Error> =
tauri_plugin_store::with_store(app, stores, path, |store| {
store.insert("adbPath".to_string(), serde_json::json!(adb_path))?;
*share::ADB_PATH.lock().unwrap() = adb_path;
Ok(())
});
match store_res {
Ok(_) => Ok(()),
Err(e) => Err(e.to_string()),
}
}
#[tokio::main]
async fn main() {
tauri::Builder::default()
@ -168,8 +186,16 @@ async fn main() {
let stores = app
.app_handle()
.state::<tauri_plugin_store::StoreCollection<tauri::Wry>>();
let path = std::path::PathBuf::from("store.bin");
let path: std::path::PathBuf = std::path::PathBuf::from("store.bin");
tauri_plugin_store::with_store(app.app_handle().clone(), stores, path, |store| {
// load adb path
match store.get("adbPath") {
Some(value) => *share::ADB_PATH.lock().unwrap() = value.to_string(),
None => store
.insert("adbPath".to_string(), serde_json::json!("adb"))
.unwrap(),
};
// restore window position and size
match store.get("maskArea") {
Some(value) => {
@ -239,7 +265,8 @@ async fn main() {
get_device_screen_size,
adb_connect,
load_default_keyconfig,
check_adb_available
check_adb_available,
set_adb_path
])
.run(tauri::generate_context!())
.expect("error while running tauri application");

View File

@ -21,3 +21,7 @@ impl ClientInfo {
lazy_static! {
pub static ref CLIENT_INFO: Mutex<Option<ClientInfo>> = Mutex::new(None);
}
lazy_static! {
pub static ref ADB_PATH: Mutex<String> = Mutex::new(String::from("adb"));
}

View File

@ -320,8 +320,13 @@ async function connectDevice() {
}
store.showLoading();
try {
message.info(await adbConnect(wireless_address.value));
await refreshDevices();
} catch (e) {
message.error("t('pages.Device.adbConnectError')");
console.error(e);
}
}
function connectWS() {

View File

@ -1,6 +1,12 @@
<script setup lang="ts">
import { h, nextTick, onActivated, onMounted, ref } from "vue";
import { NDialog, NInput, useDialog, useMessage } from "naive-ui";
import {
MessageReactive,
NDialog,
NInput,
useDialog,
useMessage,
} from "naive-ui";
import { useGlobalStore } from "../store/global";
import { onBeforeRouteLeave, useRouter } from "vue-router";
import {
@ -60,6 +66,7 @@ onActivated(async () => {
});
onMounted(async () => {
store.checkAdb = checkAdb;
await checkAdb();
await loadLocalStore();
store.checkUpdate = checkUpdate;
@ -67,11 +74,16 @@ onMounted(async () => {
if (store.checkUpdateAtStart) checkUpdate();
});
let checkAdbMessage: MessageReactive | null = null;
async function checkAdb() {
try {
if (checkAdbMessage) {
checkAdbMessage.destroy();
checkAdbMessage = null;
}
await checkAdbAvailable();
} catch (e) {
message.error(t("pages.Mask.checkAdb", [e]), {
checkAdbMessage = message.error(t("pages.Mask.checkAdb", [e]), {
duration: 0,
});
}

View File

@ -14,14 +14,20 @@ import {
NCard,
NIcon,
NSelect,
NInputGroup,
useMessage,
} from "naive-ui";
import { relaunch } from "@tauri-apps/plugin-process";
import { onMounted, ref } from "vue";
import i18n from "../../i18n";
import { useI18n } from "vue-i18n";
import { setAdbPath } from "../../invoke";
import { useGlobalStore } from "../../store/global";
const { t } = useI18n();
const localStore = new Store("store.bin");
const store = useGlobalStore();
const message = useMessage();
const dialog = useDialog();
const localStoreEntries = ref<[string, unknown][]>([]);
@ -36,9 +42,12 @@ const languageOptions = [
const curLanguage = ref("en-US");
const adbPath = ref("");
onMounted(async () => {
refreshLocalData();
curLanguage.value = (await localStore.get<string>("language")) ?? "en-US";
adbPath.value = (await localStore.get<string>("adbPath")) ?? "";
});
async function refreshLocalData() {
@ -88,6 +97,15 @@ function changeLanguage(language: "zh-CN" | "en-US") {
localStore.set("language", language);
i18n.global.locale.value = language;
}
async function adjustAdbPath() {
store.showLoading();
await setAdbPath(adbPath.value);
message.success(t("pages.Setting.Basic.adbPath.setSuccess"));
await store.checkAdb();
adbPath.value = (await localStore.get<string>("adbPath")) ?? "";
store.hideLoading();
}
</script>
<template>
@ -99,6 +117,17 @@ function changeLanguage(language: "zh-CN" | "en-US") {
:options="languageOptions"
style="max-width: 300px; margin: 20px 0"
/>
<NH4 prefix="bar">{{ $t("pages.Setting.Basic.adbPath.title") }}</NH4>
<NInputGroup style="max-width: 300px; margin-bottom: 20px">
<NInput
v-model:value="adbPath"
clearable
:placeholder="$t('pages.Setting.Basic.adbPath.placeholder')"
/>
<NButton type="primary" @click="adjustAdbPath">{{
$t("pages.Setting.Basic.adbPath.set")
}}</NButton>
</NInputGroup>
<NFlex justify="space-between">
<NH4 prefix="bar">{{ $t("pages.Setting.Basic.localStore") }}</NH4>
<NFlex>

View File

@ -35,7 +35,8 @@
"inputWsAddress": "Please enter the Websocket address",
"wsClose": "Close",
"wsConnect": "Control",
"adbDeviceError": "Unable to get available devices"
"adbDeviceError": "Unable to get available devices",
"adbConnectError": "Wireless connection failed"
},
"Mask": {
"inputBoxPlaceholder": "Input text and then press enter/esc",
@ -100,7 +101,13 @@
},
"language": "Language",
"localStore": "Local data",
"delCurData": "Delete current data"
"delCurData": "Delete current data",
"adbPath": {
"placeholder": "adb path",
"set": "Save",
"setSuccess": "adb path set successfully",
"title": "adb path"
}
},
"About": {
"introduction": "A Scrcpy client in Rust & Tarui aimed at providing mouse and key mapping to control Android device.",

View File

@ -35,7 +35,8 @@
"wsAddress": "Websocket 地址",
"wsClose": "断开",
"wsConnect": "控制",
"adbDeviceError": "无法获取可用设备"
"adbDeviceError": "无法获取可用设备",
"adbConnectError": "无线连接失败"
},
"Mask": {
"keyconfigException": "按键方案异常,请删除此方案",
@ -100,7 +101,13 @@
},
"language": "语言",
"localStore": "本地数据",
"delCurData": "删除当前数据"
"delCurData": "删除当前数据",
"adbPath": {
"setSuccess": "adb 路径设置成功",
"title": "adb 路径",
"placeholder": "adb 路径",
"set": "设置"
}
},
"About": {
"about": "关于",

View File

@ -55,4 +55,8 @@ export async function checkAdbAvailable(): Promise<void>{
return await invoke("check_adb_available");
}
export async function setAdbPath(path: string): Promise<string> {
return await invoke("set_adb_path", { adbPath: path });
}
export type { Device };

View File

@ -30,6 +30,7 @@ export const useGlobalStore = defineStore("global", () => {
const showInputBox: (_: boolean) => void = (_: boolean) => {};
let checkUpdate: () => Promise<void> = async () => {};
let checkAdb: () => Promise<void> = async () => {};
function applyEditKeyMappingList(): boolean {
const set = new Set<string>();
@ -103,5 +104,6 @@ export const useGlobalStore = defineStore("global", () => {
resetEditKeyMappingList,
setKeyMappingIndex,
checkUpdate,
checkAdb,
};
});