mirror of
https://github.com/AkiChase/scrcpy-mask
synced 2025-02-22 14:42:15 +08:00
feat(websocket): add external control
This commit is contained in:
parent
e832abff58
commit
365c915103
@ -40,13 +40,13 @@ import {
|
||||
useMessage,
|
||||
NInputGroup,
|
||||
} from "naive-ui";
|
||||
import { CloseCircle, InformationCircle } from "@vicons/ionicons5";
|
||||
import { Refresh } from "@vicons/ionicons5";
|
||||
import { CloseCircle, InformationCircle, Refresh } from "@vicons/ionicons5";
|
||||
import { UnlistenFn, listen } from "@tauri-apps/api/event";
|
||||
import { Store } from "@tauri-apps/plugin-store";
|
||||
import { shutdown } from "../frontcommand/scrcpyMaskCmd";
|
||||
import { useGlobalStore } from "../store/global";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { closeExternalControl, connectExternalControl } from "../websocket";
|
||||
|
||||
const { t } = useI18n();
|
||||
const dialog = useDialog();
|
||||
@ -54,7 +54,8 @@ const store = useGlobalStore();
|
||||
const message = useMessage();
|
||||
|
||||
const port = ref(27183);
|
||||
const address = ref("");
|
||||
const wireless_address = ref("");
|
||||
const ws_address = ref("");
|
||||
|
||||
const localStore = new Store("store.bin");
|
||||
|
||||
@ -300,15 +301,29 @@ async function refreshDevices() {
|
||||
}
|
||||
|
||||
async function connectDevice() {
|
||||
if (!address.value) {
|
||||
if (!wireless_address.value) {
|
||||
message.error(t("pages.Device.inputWirelessAddress"));
|
||||
return;
|
||||
}
|
||||
|
||||
store.showLoading();
|
||||
message.info(await adbConnect(address.value));
|
||||
message.info(await adbConnect(wireless_address.value));
|
||||
await refreshDevices();
|
||||
}
|
||||
|
||||
function connectWS() {
|
||||
if (!ws_address.value) {
|
||||
message.error(t("pages.Device.inputWsAddress"));
|
||||
return;
|
||||
}
|
||||
|
||||
store.showLoading();
|
||||
connectExternalControl(ws_address.value, message, store, t);
|
||||
}
|
||||
|
||||
function closeWS() {
|
||||
closeExternalControl();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -327,7 +342,7 @@ async function connectDevice() {
|
||||
<NH4 prefix="bar">{{ $t("pages.Device.wireless") }}</NH4>
|
||||
<NInputGroup style="max-width: 300px">
|
||||
<NInput
|
||||
v-model:value="address"
|
||||
v-model:value="wireless_address"
|
||||
clearable
|
||||
:placeholder="$t('pages.Device.wirelessPlaceholder')"
|
||||
/>
|
||||
@ -335,6 +350,24 @@ async function connectDevice() {
|
||||
$t("pages.Device.connect")
|
||||
}}</NButton>
|
||||
</NInputGroup>
|
||||
<NH4 prefix="bar">{{ $t("pages.Device.externalControl") }}</NH4>
|
||||
<NInputGroup style="max-width: 300px">
|
||||
<NInput
|
||||
v-model:value="ws_address"
|
||||
clearable
|
||||
:placeholder="$t('pages.Device.wsAddress')"
|
||||
:disabled="store.externalControlled"
|
||||
/>
|
||||
<NButton
|
||||
v-if="store.externalControlled"
|
||||
type="error"
|
||||
@click="closeWS"
|
||||
>{{ $t("pages.Device.wsClose") }}</NButton
|
||||
>
|
||||
<NButton v-else type="primary" @click="connectWS">{{
|
||||
$t("pages.Device.wsConnect")
|
||||
}}</NButton>
|
||||
</NInputGroup>
|
||||
<NH4 prefix="bar">{{ $t("pages.Device.deviceSize.title") }}</NH4>
|
||||
<NFlex justify="left" align="center">
|
||||
<NFormItem :label="$t('pages.Device.deviceSize.width')">
|
||||
|
@ -37,7 +37,12 @@
|
||||
"availableDevice": "Available devices",
|
||||
"noControledDevice": "No Controled Device",
|
||||
"alreadyControled": "Controlled device already exists",
|
||||
"alreadyDisconnected": "Controlled device connection has been disconnected"
|
||||
"alreadyDisconnected": "Controlled device connection has been disconnected",
|
||||
"externalControl": "External control",
|
||||
"wsAddress": "Websocket address",
|
||||
"inputWsAddress": "Please enter the Websocket address",
|
||||
"wsClose": "Close",
|
||||
"wsConnect": "Control"
|
||||
},
|
||||
"Mask": {
|
||||
"inputBoxPlaceholder": "Input text and then press enter/esc",
|
||||
@ -218,5 +223,10 @@
|
||||
},
|
||||
"sidebar": {
|
||||
"noControledDevice": "No devices are controlled"
|
||||
},
|
||||
"websocket": {
|
||||
"open": "Connected to external control server",
|
||||
"close": "External control connection disconnected",
|
||||
"error": "Something was wrong, the exter connection is closed"
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ const localStore = new Store("store.bin");
|
||||
|
||||
const i18n = createI18n({
|
||||
allowComposition: true,
|
||||
legacy: false,
|
||||
messages: {
|
||||
"en-US": enUS,
|
||||
"zh-CN": zhCN,
|
||||
@ -15,7 +16,7 @@ const i18n = createI18n({
|
||||
});
|
||||
|
||||
localStore.get<"en-US" | "zh-CN">("language").then((language) => {
|
||||
i18n.global.locale = language ?? "en-US";
|
||||
i18n.global.locale.value = language ?? "en-US";
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
|
@ -37,7 +37,12 @@
|
||||
"noControledDevice": "无受控设备",
|
||||
"availableDevice": "可用设备",
|
||||
"alreadyControled": "已存在受控设备",
|
||||
"alreadyDisconnected": "受控设备连接已断开"
|
||||
"alreadyDisconnected": "受控设备连接已断开",
|
||||
"inputWsAddress": "请输入 Websocket 地址",
|
||||
"externalControl": "外部控制",
|
||||
"wsAddress": "Websocket 地址",
|
||||
"wsClose": "断开",
|
||||
"wsConnect": "控制"
|
||||
},
|
||||
"Mask": {
|
||||
"keyconfigException": "按键方案异常,请删除此方案",
|
||||
@ -218,5 +223,10 @@
|
||||
},
|
||||
"sidebar": {
|
||||
"noControledDevice": "未控制任何设备"
|
||||
},
|
||||
"websocket": {
|
||||
"open": "已连接到外部控制服务端",
|
||||
"close": "外部控制连接断开",
|
||||
"error": "未知错误,外部控制连接断开"
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@ export const useGlobalStore = defineStore("global", () => {
|
||||
localStore.set("curKeyMappingIndex", index);
|
||||
}
|
||||
|
||||
const externalControlled = ref(false);
|
||||
|
||||
// persistent storage
|
||||
const screenSizeW: Ref<number> = ref(0);
|
||||
const screenSizeH: Ref<number> = ref(0);
|
||||
@ -88,6 +90,7 @@ export const useGlobalStore = defineStore("global", () => {
|
||||
curKeyMappingIndex,
|
||||
maskButton,
|
||||
checkUpdateAtStart,
|
||||
externalControlled,
|
||||
// in-memory storage
|
||||
showLoading,
|
||||
hideLoading,
|
||||
|
81
src/websocket.ts
Normal file
81
src/websocket.ts
Normal file
@ -0,0 +1,81 @@
|
||||
import { useMessage } from "naive-ui";
|
||||
import { useGlobalStore } from "./store/global";
|
||||
import { sendKey, shutdown, swipe, touch } from "./frontcommand/scrcpyMaskCmd";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
let ws: WebSocket;
|
||||
let sharedMessage: ReturnType<typeof useMessage>;
|
||||
let sharedStore: ReturnType<typeof useGlobalStore>;
|
||||
let t: ReturnType<typeof useI18n>["t"];
|
||||
|
||||
export function connectExternalControl(
|
||||
url: string,
|
||||
message: ReturnType<typeof useMessage>,
|
||||
store: ReturnType<typeof useGlobalStore>,
|
||||
i18nT: ReturnType<typeof useI18n>["t"]
|
||||
) {
|
||||
sharedMessage = message;
|
||||
sharedStore = store;
|
||||
t = i18nT;
|
||||
|
||||
ws = new WebSocket(url);
|
||||
ws.addEventListener("open", handleOpen);
|
||||
ws.addEventListener("message", handleMessage);
|
||||
ws.addEventListener("close", handleClose);
|
||||
ws.addEventListener("error", handleError);
|
||||
}
|
||||
|
||||
export function closeExternalControl() {
|
||||
if (ws) ws.close();
|
||||
}
|
||||
|
||||
function handleOpen() {
|
||||
sharedStore.externalControlled = true;
|
||||
sharedStore.hideLoading();
|
||||
sharedMessage.success(t("websocket.open"));
|
||||
}
|
||||
|
||||
async function handleMessage(event: MessageEvent) {
|
||||
try {
|
||||
const msg = JSON.parse(event.data);
|
||||
if (msg.type === "showMessage") {
|
||||
sharedMessage.create(msg.msgContent, { type: msg.msgType });
|
||||
} else if (msg.type === "getControlledDevice") {
|
||||
msg.controledDevice = sharedStore.controledDevice;
|
||||
ws.send(JSON.stringify(msg));
|
||||
} else if (msg.type === "sendKey") {
|
||||
delete msg.type;
|
||||
await sendKey(msg);
|
||||
} else if (msg.type === "touch") {
|
||||
msg.screen = { w: sharedStore.screenSizeW, h: sharedStore.screenSizeH };
|
||||
delete msg.type;
|
||||
await touch(msg);
|
||||
} else if (msg.type === "swipe") {
|
||||
console.log(msg);
|
||||
msg.screen = { w: sharedStore.screenSizeW, h: sharedStore.screenSizeH };
|
||||
delete msg.type;
|
||||
await swipe(msg);
|
||||
} else if (msg.type === "shutdown") {
|
||||
await shutdown();
|
||||
sharedStore.controledDevice = null;
|
||||
} else {
|
||||
console.error("Invalid message received", msg);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Message received failed", error);
|
||||
}
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
sharedMessage.info(t("websocket.close"));
|
||||
ws.close();
|
||||
sharedStore.externalControlled = false;
|
||||
sharedStore.hideLoading();
|
||||
}
|
||||
|
||||
function handleError() {
|
||||
sharedMessage.error(t("websocket.error"));
|
||||
ws.close();
|
||||
sharedStore.externalControlled = false;
|
||||
sharedStore.hideLoading();
|
||||
}
|
Loading…
Reference in New Issue
Block a user