diff --git a/package.json b/package.json index b594c24..6fc2b70 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@tauri-apps/api": ">=2.0.0-beta.8", + "@tauri-apps/plugin-clipboard-manager": "2.1.0-beta.1", "@tauri-apps/plugin-http": "2.0.0-beta.3", "@tauri-apps/plugin-process": "2.0.0-beta.2", "@tauri-apps/plugin-shell": "2.0.0-beta.3", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9433407..4b5a1bb 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -21,3 +21,4 @@ tokio = { version = "1.36.0", features = ["rt-multi-thread", "net", "macros", "i tauri-plugin-process = "2.0.0-beta" tauri-plugin-shell = "2.0.0-beta" tauri-plugin-http = "2.0.0-beta" +tauri-plugin-clipboard-manager = "2.1.0-beta.2" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index 8b1ebe9..70abfb6 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -34,11 +34,16 @@ { "identifier": "http:default", "allow": [ - { "url": "https://api.github.com/repos/AkiChase/scrcpy-mask/*" } + { + "url": "https://api.github.com/repos/AkiChase/scrcpy-mask/*" + } ] }, "http:allow-fetch", "app:default", - "app:allow-version" + "app:allow-version", + "clipboard-manager:default", + "clipboard-manager:allow-read-text", + "clipboard-manager:allow-write-text" ] } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 85eb83b..db44892 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -4,5 +4,5 @@ pub mod client; pub mod control_msg; pub mod resource; pub mod scrcpy_mask_cmd; -pub mod socket; pub mod share; +pub mod socket; diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 5e53b5b..f8abaa6 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -181,6 +181,7 @@ fn set_adb_path(adb_path: String, app: tauri::AppHandle) -> Result<(), String> { #[tokio::main] async fn main() { tauri::Builder::default() + .plugin(tauri_plugin_clipboard_manager::init()) .plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_process::init()) diff --git a/src/components/Device.vue b/src/components/Device.vue index bcdcd01..b00b6ed 100644 --- a/src/components/Device.vue +++ b/src/components/Device.vue @@ -45,6 +45,7 @@ import { useGlobalStore } from "../store/global"; import { useI18n } from "vue-i18n"; import { closeExternalControl, connectExternalControl } from "../websocket"; import { LogicalSize, getCurrent } from "@tauri-apps/api/window"; +import { writeText } from "@tauri-apps/plugin-clipboard-manager"; const { t } = useI18n(); const dialog = useDialog(); @@ -73,15 +74,8 @@ onMounted(async () => { case "ClipboardChanged": if (payload.clipboard === lastClipboard) break; lastClipboard = payload.clipboard; - navigator.clipboard - .writeText(payload.clipboard) - .then(() => { - message.info(t("pages.Device.clipboard.deviceSync.success")); - }) - .catch((e) => { - console.error(e); - message.error(t("pages.Device.clipboard.deviceSync.failed")); - }); + writeText(payload.clipboard); + console.log(payload); break; case "ClipboardSetAck": break; diff --git a/src/components/keyboard/KeySetting.vue b/src/components/keyboard/KeySetting.vue index aecafba..1070c95 100644 --- a/src/components/keyboard/KeySetting.vue +++ b/src/components/keyboard/KeySetting.vue @@ -19,6 +19,7 @@ import { loadDefaultKeyconfig } from "../../invoke"; import { KeyMappingConfig } from "../../keyMappingConfig"; import { useKeyboardStore } from "../../store/keyboard"; import { useI18n } from "vue-i18n"; +import { writeText } from "@tauri-apps/plugin-clipboard-manager"; const { t } = useI18n(); const store = useGlobalStore(); @@ -251,8 +252,7 @@ function renameKeyMappingConfig() { function exportKeyMappingConfig() { const config = store.keyMappingConfigList[store.curKeyMappingIndex]; const data = JSON.stringify(config, null, 2); - navigator.clipboard - .writeText(data) + writeText(data) .then(() => { message.success(t("pages.KeyBoard.KeySetting.exportSuccess")); }) diff --git a/src/frontcommand/controlMsg.ts b/src/frontcommand/controlMsg.ts index b4bfe2b..f2d57c9 100644 --- a/src/frontcommand/controlMsg.ts +++ b/src/frontcommand/controlMsg.ts @@ -163,13 +163,13 @@ interface InjectKeycode { metastate: AndroidMetastate; } -enum ScCopyKey { +export enum ScCopyKey { SC_COPY_KEY_NONE, SC_COPY_KEY_COPY, SC_COPY_KEY_CUT, } -enum ScScreenPowerMode { +export enum ScScreenPowerMode { // see SC_SCREEN_POWER_MODE_OFF = 0, SC_SCREEN_POWER_MODE_NORMAL = 2, diff --git a/src/hotkey.ts b/src/hotkey.ts index 618fd71..8fe93bf 100644 --- a/src/hotkey.ts +++ b/src/hotkey.ts @@ -23,6 +23,7 @@ import { } from "./keyMappingConfig"; import { useGlobalStore } from "./store/global"; import { LogicalPosition, getCurrent } from "@tauri-apps/api/window"; +import { readText } from "@tauri-apps/plugin-clipboard-manager"; import { useI18n } from "vue-i18n"; import { KeyToCodeMap } from "./frontcommand/KeyToCodeMap"; import { @@ -30,7 +31,7 @@ import { AndroidMetastate, } from "./frontcommand/android"; import { UIEventsCode } from "./frontcommand/UIEventsCode"; -import { sendInjectKeycode } from "./frontcommand/controlMsg"; +import { sendInjectKeycode, sendSetClipboard } from "./frontcommand/controlMsg"; function clientxToPosx(clientx: number) { return clientx < 70 @@ -1046,6 +1047,8 @@ export class KeyInputHandler { let action: AndroidKeyEventAction; let repeatCount = 0; if (event.type === "keydown") { + if (event.getModifierState("Control") && event.code === "KeyV") return; + action = AndroidKeyEventAction.AKEY_EVENT_ACTION_DOWN; if (event.repeat) { let count = KeyInputHandler.repeatCounter.get(keycode); @@ -1058,6 +1061,18 @@ export class KeyInputHandler { KeyInputHandler.repeatCounter.set(keycode, count); } } else if (event.type === "keyup") { + if (event.getModifierState("Control") && event.code === "KeyV") { + (async () => { + const text = await readText(); + await sendSetClipboard({ + sequence: Math.floor(Math.random() * 10000), + text, + paste: true, + }); + })(); + return; + } + action = AndroidKeyEventAction.AKEY_EVENT_ACTION_UP; KeyInputHandler.repeatCounter.delete(keycode); } else { @@ -1078,12 +1093,6 @@ export class KeyInputHandler { ? AndroidMetastate.AMETA_NUM_LOCK_ON : 0); - // const controlMessage = new KeyCodeControlMessage( - // action, - // keyCode, - // repeatCount, - // metaState - // ); sendInjectKeycode({ action, keycode, diff --git a/src/i18n/en-US.json b/src/i18n/en-US.json index 71420b6..e956764 100644 --- a/src/i18n/en-US.json +++ b/src/i18n/en-US.json @@ -36,13 +36,7 @@ "wsConnect": "Control", "adbDeviceError": "Unable to get available devices", "adbConnectError": "Wireless connection failed", - "rotation": "Device rotation {0}°", - "clipboard": { - "deviceSync": { - "success": "Device clipboard synced", - "failed": "Device clipboard sync failed" - } - } + "rotation": "Device rotation {0}°" }, "Mask": { "keyconfigException": "The key mapping config is abnormal, please delete this config", diff --git a/src/i18n/zh-CN.json b/src/i18n/zh-CN.json index 325424f..f7b32d3 100644 --- a/src/i18n/zh-CN.json +++ b/src/i18n/zh-CN.json @@ -36,13 +36,7 @@ "wsConnect": "控制", "adbDeviceError": "无法获取可用设备", "adbConnectError": "无线连接失败", - "rotation": "设备旋转 {0}°", - "clipboard": { - "deviceSync": { - "success": "已从设备同步剪切板", - "failed": "从设备同步剪切板失败" - } - } + "rotation": "设备旋转 {0}°" }, "Mask": { "keyconfigException": "按键方案异常,请删除此方案",