From b1f5960306f57b2267564a159be1110ddaf9c73c Mon Sep 17 00:00:00 2001 From: AkiChase <1003019131@qq.com> Date: Wed, 12 Mar 2025 17:26:55 +0800 Subject: [PATCH] feat: add help tooltip --- src/components/Device.vue | 45 ++++++++++++++++++++++++------ src/components/ScreenStream.vue | 20 +++++++++---- src/components/setting/About.vue | 12 +++----- src/components/setting/Mask.vue | 30 ++++++++++++-------- src/components/setting/Setting.vue | 1 + src/css/global.scss | 1 + src/i18n/en-US.json | 15 +++++++--- src/i18n/zh-CN.json | 15 +++++++--- src/store/noneReactiveStore.ts | 3 ++ src/tools/hooks.ts | 20 +++++++------ src/tools/invoke.ts | 4 +++ src/tools/tools.ts | 5 ++++ 12 files changed, 119 insertions(+), 52 deletions(-) diff --git a/src/components/Device.vue b/src/components/Device.vue index 8235f4d..ae1b9dd 100644 --- a/src/components/Device.vue +++ b/src/components/Device.vue @@ -18,6 +18,7 @@ import { getDeviceScreenSize, adbConnect, getCurClientInfo, + adbRestartServer, } from "../tools/invoke"; import { NH4, @@ -34,6 +35,7 @@ import { useDialog, useMessage, NInputGroup, + NSpace, } from "naive-ui"; import { CloseCircle, InformationCircle, Refresh } from "@vicons/ionicons5"; import { UnlistenFn, listen } from "@tauri-apps/api/event"; @@ -47,6 +49,7 @@ import { import { LogicalSize, getCurrentWindow } from "@tauri-apps/api/window"; import { writeText } from "@tauri-apps/plugin-clipboard-manager"; import ButtonWithTip from "./common/ButtonWithTip.vue"; +import { NonReactiveStore } from "../store/noneReactiveStore"; const { t } = useI18n(); const dialog = useDialog(); @@ -328,6 +331,21 @@ async function refreshDevices() { store.hideLoading(); } +async function restartAdb() { + if (NonReactiveStore.mem.adbUnavailableMsgIns !== null) { + message.error(t("pages.Device.adbUnavailable")); + return; + } + store.showLoading(); + try { + await adbRestartServer(); + } catch (e) { + message.error(t("pages.Device.adbRestartError")); + console.error(e); + } + store.hideLoading(); +} + async function connectDevice() { if (!wireless_address.value) { message.error(t("pages.Device.inputWirelessAddress")); @@ -437,15 +455,24 @@ function closeWS() { {{ $t("pages.Device.availableDevice") }} - + + + + (null); @@ -14,16 +16,22 @@ let msgReactive: MessageReactive | null = null; function connectScreenStream() { if (streamImg.value) { - const ss = new ScreenStream(streamImg.value, NonReactiveStore.mem.screenStreamClientId); + const ss = new ScreenStream( + streamImg.value, + NonReactiveStore.mem.screenStreamClientId + ); ss.connect( store.screenStream.address, () => {}, () => { - msgReactive = message.error("投屏连接失败。关闭此信息将尝试重新连接", { - duration: 0, - closable: true, - onClose: () => connectScreenStream(), - }); + msgReactive = message.error( + t("pages.Setting.Mask.screenStream.connectError"), + { + duration: 0, + closable: true, + onClose: () => connectScreenStream(), + } + ); } ); } diff --git a/src/components/setting/About.vue b/src/components/setting/About.vue index cbe80ec..5b0460e 100644 --- a/src/components/setting/About.vue +++ b/src/components/setting/About.vue @@ -1,12 +1,12 @@ diff --git a/src/css/global.scss b/src/css/global.scss index 54baa27..26fc595 100644 --- a/src/css/global.scss +++ b/src/css/global.scss @@ -30,6 +30,7 @@ div#app { } .n-spin-container { + background-color: var(--bg-color); @include common.flexFullHeight; .n-spin-content { @include common.flexFullHeight; diff --git a/src/i18n/en-US.json b/src/i18n/en-US.json index 78540ab..420f703 100644 --- a/src/i18n/en-US.json +++ b/src/i18n/en-US.json @@ -38,7 +38,10 @@ "adbConnectError": "Wireless connection failed", "rotation": "Device rotation {0}°", "btnShutdown": "Shutdown control", - "btnRefresh": "Refresh" + "btnRefresh": "Refresh", + "btnReStart": "Restart ADB", + "adbRestartError": "ADB Restart Failed", + "adbUnavailable": "ADB Unavailable" }, "Mask": { "keyconfigException": "The key mapping config is abnormal, please delete this config", @@ -97,8 +100,11 @@ "screenStream": { "enable": "Enable mirror", "address": "Screen mirror address", - "addressPlaceholder": "Please enter the ScreenStream screen mirror address" - } + "addressPlaceholder": "Please enter the ScreenStream screen mirror address", + "connectError": "ScreenStream connection failed. Closing this message will attempt to reconnect", + "btnHelp": "ScreenStream is an Android screen mirror app with 0.5-1s screen delay, only as a complementary solution to Scrcpy Mask's screen mirror (click to open its project homepage)" + }, + "btnAreaAdjustTip": "Setting the mask area" }, "Basic": { "language": "Language", @@ -282,5 +288,6 @@ "open": "Connected to external control server", "close": "External control connection disconnected", "error": "Something was wrong, the exter connection is closed" - } + }, + "screenStream": {} } diff --git a/src/i18n/zh-CN.json b/src/i18n/zh-CN.json index addb58e..eadf413 100644 --- a/src/i18n/zh-CN.json +++ b/src/i18n/zh-CN.json @@ -38,7 +38,10 @@ "adbConnectError": "无线连接失败", "rotation": "设备旋转 {0}°", "btnShutdown": "关闭控制", - "btnRefresh": "刷新" + "btnRefresh": "刷新", + "btnReStart": "重启ABD", + "adbRestartError": "ADB 重启失败", + "adbUnavailable": "ADB 不可用" }, "Mask": { "keyconfigException": "按键方案异常,请删除此方案", @@ -97,8 +100,11 @@ "screenStream": { "enable": "启用投屏", "address": "投屏地址", - "addressPlaceholder": "请输入 ScreenStream 投屏地址" - } + "addressPlaceholder": "请输入 ScreenStream 投屏地址", + "connectError": "ScreenStream 投屏连接失败。关闭此信息将尝试重新连接", + "btnHelp": "ScreenStream 是一款安卓投屏App,存在0.5-1s的画面延迟,仅作为 Scrcpy Mask 的投屏补充方案(点击打开其项目主页)" + }, + "btnAreaAdjustTip": "设置蒙版区域" }, "Basic": { "language": "语言", @@ -282,5 +288,6 @@ "open": "已连接到外部控制服务端", "close": "外部控制连接断开", "error": "未知错误,外部控制连接断开" - } + }, + "screenStream": {} } diff --git a/src/store/noneReactiveStore.ts b/src/store/noneReactiveStore.ts index a391486..64f262c 100644 --- a/src/store/noneReactiveStore.ts +++ b/src/store/noneReactiveStore.ts @@ -1,8 +1,10 @@ +import { MessageReactive } from "naive-ui"; import { LocalStore } from "./localStore"; interface MemType { screenStreamClientId: string; keyInputFlag: boolean; + adbUnavailableMsgIns: MessageReactive | null; } interface LocalType { @@ -19,6 +21,7 @@ export class NonReactiveStore { static mem: MemType = { screenStreamClientId: "", keyInputFlag: false, + adbUnavailableMsgIns: null, }; static local: LocalType = { diff --git a/src/tools/hooks.ts b/src/tools/hooks.ts index e55e76b..ab58c8b 100644 --- a/src/tools/hooks.ts +++ b/src/tools/hooks.ts @@ -1,13 +1,13 @@ import { getVersion } from "@tauri-apps/api/app"; -import { MessageReactive, useDialog, useMessage } from "naive-ui"; +import { useDialog, useMessage } from "naive-ui"; import { h } from "vue"; import { useI18n } from "vue-i18n"; import { fetch } from "@tauri-apps/plugin-http"; import { compareVersion } from "./tools"; import { checkAdbAvailable } from "./invoke"; +import { NonReactiveStore } from "../store/noneReactiveStore"; // TODO use markdown to render update info -// TODO check screen stream available function renderUpdateInfo(content: string) { const pList = content.split("\r\n").map((line: string) => h("p", line)); @@ -56,22 +56,24 @@ export function useCheckUpdate() { }; } -let checkAdbMessage: MessageReactive | null = null; export function useCheckAdb() { const message = useMessage(); const { t } = useI18n(); return async function checkAdb() { try { - if (checkAdbMessage) { - checkAdbMessage.destroy(); - checkAdbMessage = null; + if (NonReactiveStore.mem.adbUnavailableMsgIns) { + NonReactiveStore.mem.adbUnavailableMsgIns.destroy(); + NonReactiveStore.mem.adbUnavailableMsgIns = null; } await checkAdbAvailable(); } catch (e) { - checkAdbMessage = message.error(t("pages.Mask.checkAdb", [e]), { - duration: 0, - }); + NonReactiveStore.mem.adbUnavailableMsgIns = message.error( + t("pages.Mask.checkAdb", [e]), + { + duration: 0, + } + ); } }; } diff --git a/src/tools/invoke.ts b/src/tools/invoke.ts index a39f623..06b4c77 100644 --- a/src/tools/invoke.ts +++ b/src/tools/invoke.ts @@ -9,6 +9,10 @@ export async function adbDevices(): Promise { return await invoke("adb_devices"); } +export async function adbRestartServer(): Promise { + return await invoke("adb_restart_server"); +} + export async function forwardServerPort( id: string, scid: string, diff --git a/src/tools/tools.ts b/src/tools/tools.ts index c374eb8..91da23e 100644 --- a/src/tools/tools.ts +++ b/src/tools/tools.ts @@ -1,4 +1,5 @@ import { getCurrentWindow, LogicalSize } from "@tauri-apps/api/window"; +import { open as shellOpen } from "@tauri-apps/plugin-shell"; export function compareVersion(v1: string, v2: string) { const [x1, y1, z1] = v1.split("."); @@ -36,3 +37,7 @@ export async function cleanAfterimage() { await appWindow.setSize(newSize); await appWindow.setSize(oldSize); } + +export function openWebsite(url: string) { + shellOpen(url); +}