mirror of
https://github.com/viarotel-org/escrcpy.git
synced 2025-01-19 01:24:12 +01:00
perf: 🚀 合并无线连接及有线连接到设备列表
This commit is contained in:
parent
63a3de514b
commit
e84f24e816
@ -10,6 +10,11 @@ export default defineConfig({
|
|||||||
plugins: [externalizeDepsPlugin()],
|
plugins: [externalizeDepsPlugin()],
|
||||||
},
|
},
|
||||||
preload: {
|
preload: {
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@resources': resolve('resources'),
|
||||||
|
},
|
||||||
|
},
|
||||||
plugins: [externalizeDepsPlugin()],
|
plugins: [externalizeDepsPlugin()],
|
||||||
},
|
},
|
||||||
renderer: {
|
renderer: {
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@renderer/*": ["src/renderer/src/*"]
|
"@renderer/*": ["src/renderer/src/*"],
|
||||||
|
"@resources/*": ["resources/*"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@ function createWindow() {
|
|||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: join(__dirname, '../preload/index.js'),
|
preload: join(__dirname, '../preload/index.js'),
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
devTools: true,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { contextBridge } from 'electron'
|
import { contextBridge } from 'electron'
|
||||||
|
|
||||||
export function addContext(key, value) {
|
export function exposeContext(key, value) {
|
||||||
if (process.contextIsolated) {
|
if (process.contextIsolated) {
|
||||||
try {
|
try {
|
||||||
contextBridge.exposeInMainWorld(key, value)
|
contextBridge.exposeInMainWorld(key, value)
|
||||||
|
@ -1,74 +1,4 @@
|
|||||||
import { electronAPI } from '@electron-toolkit/preload'
|
import plugins from './plugins/index.js'
|
||||||
import { Adb } from '@devicefarmer/adbkit'
|
import { exposeContext } from './helpers/index.js'
|
||||||
|
|
||||||
import scrcpyPath from '../../resources/core/scrcpy.exe?asset&asarUnpack'
|
plugins.install(exposeContext)
|
||||||
import adbPath from '../../resources/core/adb.exe?asset&asarUnpack'
|
|
||||||
import { addContext } from './helpers/index.js'
|
|
||||||
|
|
||||||
const util = require('node:util')
|
|
||||||
const exec = util.promisify(require('node:child_process').exec)
|
|
||||||
|
|
||||||
// Custom APIs for renderer
|
|
||||||
const api = {}
|
|
||||||
|
|
||||||
// Use `contextBridge` APIs to expose Electron APIs to
|
|
||||||
// renderer only if context isolation is enabled, otherwise
|
|
||||||
// just add to the DOM global.
|
|
||||||
addContext('electron', electronAPI)
|
|
||||||
addContext('api', api)
|
|
||||||
|
|
||||||
addContext('adbkit', () => {
|
|
||||||
const client = Adb.createClient({ bin: adbPath })
|
|
||||||
console.log('client', client)
|
|
||||||
|
|
||||||
const getDevices = async () => await client.listDevicesWithPaths()
|
|
||||||
const shell = async (id, command) => await client.getDevice(id).shell(command)
|
|
||||||
const kill = async (...params) => await client.kill(...params)
|
|
||||||
const connect = async (...params) => await client.connect(...params)
|
|
||||||
const disconnect = async (...params) => await client.disconnect(...params)
|
|
||||||
|
|
||||||
const watch = async (callback) => {
|
|
||||||
const tracker = await client.trackDevices()
|
|
||||||
tracker.on('add', (device) => {
|
|
||||||
callback(device)
|
|
||||||
})
|
|
||||||
|
|
||||||
tracker.on('remove', (device) => {
|
|
||||||
callback(device)
|
|
||||||
})
|
|
||||||
|
|
||||||
tracker.on('end', (ret) => {
|
|
||||||
callback(ret)
|
|
||||||
})
|
|
||||||
|
|
||||||
tracker.on('error', (err) => {
|
|
||||||
callback(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
const close = () => tracker.end()
|
|
||||||
|
|
||||||
return close
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('beforeunload', () => {
|
|
||||||
kill()
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
getDevices,
|
|
||||||
shell,
|
|
||||||
kill,
|
|
||||||
connect,
|
|
||||||
disconnect,
|
|
||||||
watch,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
addContext('scrcpy', () => {
|
|
||||||
const shell = command =>
|
|
||||||
exec(`${scrcpyPath} ${command}`, { env: { ...process.env, ADB: adbPath } })
|
|
||||||
|
|
||||||
return {
|
|
||||||
shell,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
53
src/preload/plugins/adbkit/index.js
Normal file
53
src/preload/plugins/adbkit/index.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { Adb } from '@devicefarmer/adbkit'
|
||||||
|
import adbPath from '@resources/core/adb.exe?asset&asarUnpack'
|
||||||
|
|
||||||
|
let client = null
|
||||||
|
|
||||||
|
window.addEventListener('beforeunload', () => {
|
||||||
|
if (client) {
|
||||||
|
client.kill()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const getDevices = async () => await client.listDevicesWithPaths()
|
||||||
|
const shell = async (id, command) => await client.getDevice(id).shell(command)
|
||||||
|
const kill = async (...params) => await client.kill(...params)
|
||||||
|
const connect = async (...params) => await client.connect(...params)
|
||||||
|
const disconnect = async (...params) => await client.disconnect(...params)
|
||||||
|
|
||||||
|
const watch = async (callback) => {
|
||||||
|
const tracker = await client.trackDevices()
|
||||||
|
tracker.on('add', (device) => {
|
||||||
|
callback(device)
|
||||||
|
})
|
||||||
|
|
||||||
|
tracker.on('remove', (device) => {
|
||||||
|
callback(device)
|
||||||
|
})
|
||||||
|
|
||||||
|
tracker.on('end', (ret) => {
|
||||||
|
callback(ret)
|
||||||
|
})
|
||||||
|
|
||||||
|
tracker.on('error', (err) => {
|
||||||
|
callback(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
const close = () => tracker.end()
|
||||||
|
|
||||||
|
return close
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
client = Adb.createClient({ bin: adbPath })
|
||||||
|
console.log('client', client)
|
||||||
|
|
||||||
|
return {
|
||||||
|
getDevices,
|
||||||
|
shell,
|
||||||
|
kill,
|
||||||
|
connect,
|
||||||
|
disconnect,
|
||||||
|
watch,
|
||||||
|
}
|
||||||
|
}
|
3
src/preload/plugins/electron/index.js
Normal file
3
src/preload/plugins/electron/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { electronAPI } from '@electron-toolkit/preload'
|
||||||
|
|
||||||
|
export default () => electronAPI
|
11
src/preload/plugins/index.js
Normal file
11
src/preload/plugins/index.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import electron from './electron/index.js'
|
||||||
|
import adbkit from './adbkit/index.js'
|
||||||
|
import scrcpy from './scrcpy/index.js'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
install(expose) {
|
||||||
|
expose('electron', electron())
|
||||||
|
expose('adbkit', adbkit())
|
||||||
|
expose('scrcpy', scrcpy())
|
||||||
|
},
|
||||||
|
}
|
12
src/preload/plugins/scrcpy/index.js
Normal file
12
src/preload/plugins/scrcpy/index.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import adbPath from '@resources/core/adb.exe?asset&asarUnpack'
|
||||||
|
import scrcpyPath from '@resources/core/scrcpy.exe?asset&asarUnpack'
|
||||||
|
|
||||||
|
const util = require('node:util')
|
||||||
|
const exec = util.promisify(require('node:child_process').exec)
|
||||||
|
|
||||||
|
const shell = command =>
|
||||||
|
exec(`${scrcpyPath} ${command}`, { env: { ...process.env, ADB: adbPath } })
|
||||||
|
|
||||||
|
export default () => ({
|
||||||
|
shell,
|
||||||
|
})
|
@ -15,33 +15,27 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Wired from './components/Wired/index.vue'
|
import Devices from './components/Devices/index.vue'
|
||||||
import Wireless from './components/Wireless/index.vue'
|
|
||||||
import Advanced from './components/Advanced/index.vue'
|
import Advanced from './components/Advanced/index.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Wired,
|
Devices,
|
||||||
Wireless,
|
|
||||||
Advanced,
|
Advanced,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tabsModel: [
|
tabsModel: [
|
||||||
{
|
{
|
||||||
label: '有线模式',
|
label: '设备列表',
|
||||||
prop: 'Wired',
|
prop: 'Devices',
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '无线模式',
|
|
||||||
prop: 'Wireless',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '高级配置',
|
label: '高级配置',
|
||||||
prop: 'Advanced',
|
prop: 'Advanced',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
activeTab: 'Wired',
|
activeTab: 'Devices',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {},
|
mounted() {},
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div class="flex items-center flex-none space-x-2">
|
<div class="flex items-center flex-none space-x-2">
|
||||||
<el-input v-model="formData.host" placeholder="192.168.0.1" class="w-72">
|
<el-input v-model="formData.host" placeholder="192.168.0.1" class="w-72">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
无线调试地址
|
无线连接设备
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<div class="text-gray-500 text-sm">
|
<div class="text-gray-500 text-sm">
|
||||||
@ -37,15 +37,18 @@
|
|||||||
<el-table-column prop="id" label="设备 ID" />
|
<el-table-column prop="id" label="设备 ID" />
|
||||||
<el-table-column prop="name" label="设备名称">
|
<el-table-column prop="name" label="设备名称">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<div v-if="row.$unauthorized" class="flex items-center">
|
<div class="flex items-center">
|
||||||
<el-tooltip content="请重新插拔设备并点击允许USB调试" placement="top-start">
|
<el-tooltip
|
||||||
|
v-if="row.$unauthorized"
|
||||||
|
content="设备可能未授权成功,请重新插拔设备并点击允许USB调试"
|
||||||
|
placement="top-start"
|
||||||
|
>
|
||||||
<el-icon class="mr-1 text-red-600 text-lg">
|
<el-icon class="mr-1 text-red-600 text-lg">
|
||||||
<WarningFilled />
|
<WarningFilled />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
设备未授权
|
{{ row.name }}
|
||||||
</div>
|
</div>
|
||||||
<span v-else class="">{{ row.name }}</span>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="300" align="center">
|
<el-table-column label="操作" width="300" align="center">
|
||||||
@ -53,11 +56,11 @@
|
|||||||
<el-button type="primary" :loading="row.$loading" @click="handleStart(row)">
|
<el-button type="primary" :loading="row.$loading" @click="handleStart(row)">
|
||||||
{{ row.$loading ? '镜像中' : '开始镜像' }}
|
{{ row.$loading ? '镜像中' : '开始镜像' }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button :disabled="!row.$loading" type="default" @click="handleScreenUp(row)">
|
<el-button type="default" @click="handleScreenUp(row)">
|
||||||
点亮屏幕
|
点亮屏幕
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
:disabled="!row.$loading"
|
v-if="row.$wireless"
|
||||||
type="danger"
|
type="danger"
|
||||||
:loading="row.$stopLoading"
|
:loading="row.$stopLoading"
|
||||||
@click="handleStop(row)"
|
@click="handleStop(row)"
|
||||||
@ -146,18 +149,18 @@ export default {
|
|||||||
},
|
},
|
||||||
async getDeviceData() {
|
async getDeviceData() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
await sleep(500)
|
await sleep()
|
||||||
try {
|
try {
|
||||||
const data = await this.$adb.getDevices()
|
const data = await this.$adb.getDevices()
|
||||||
this.deviceList = (data || [])
|
this.deviceList = (data || []).map(item => ({
|
||||||
.filter(item => isIPWithPort(item.id))
|
...item,
|
||||||
.map(item => ({
|
name: item.model ? item.model.split(':')[1] : '未授权设备',
|
||||||
...item,
|
$loading: false,
|
||||||
name: item.model ? item.model.split(':')[1] : '未授权设备',
|
$stopLoading: false,
|
||||||
$loading: false,
|
$unauthorized: item.type === 'unauthorized',
|
||||||
$stopLoading: false,
|
$wireless: isIPWithPort(item.id),
|
||||||
$unauthorized: item.type === 'unauthorized',
|
}))
|
||||||
}))
|
|
||||||
console.log('getDeviceData.data', this.deviceList)
|
console.log('getDeviceData.data', this.deviceList)
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
@ -1,119 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="h-full flex flex-col">
|
|
||||||
<div class="flex items-center flex-none">
|
|
||||||
<el-button type="primary" @click="getDeviceData">
|
|
||||||
刷新设备
|
|
||||||
</el-button>
|
|
||||||
<el-button type="warning" @click="handleReset">
|
|
||||||
重启服务
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="pt-4 flex-1 h-0 overflow-hidden">
|
|
||||||
<el-table
|
|
||||||
v-loading="loading"
|
|
||||||
:element-loading-text="loadingText"
|
|
||||||
:data="deviceList"
|
|
||||||
style="width: 100%"
|
|
||||||
border
|
|
||||||
height="100%"
|
|
||||||
>
|
|
||||||
<template #empty>
|
|
||||||
<el-empty description="设备列表为空" />
|
|
||||||
</template>
|
|
||||||
<el-table-column prop="id" label="设备 ID" />
|
|
||||||
<el-table-column prop="name" label="设备名称">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<div v-if="row.$unauthorized" class="flex items-center">
|
|
||||||
<el-tooltip content="请重新插拔设备并点击允许USB调试" placement="top-start">
|
|
||||||
<el-icon class="mr-1 text-red-600 text-lg">
|
|
||||||
<WarningFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
设备未授权
|
|
||||||
</div>
|
|
||||||
<span v-else class="">{{ row.name }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" width="300" align="center">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-button type="primary" :loading="row.$loading" @click="handleStart(row)">
|
|
||||||
{{ row.$loading ? '镜像中' : '开始镜像' }}
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
:disabled="!row.$loading"
|
|
||||||
type="default"
|
|
||||||
@click="handleScreenUp(row)"
|
|
||||||
>
|
|
||||||
点亮屏幕
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { isIPWithPort, sleep } from '@renderer/utils/index.js'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
loadingText: '初始化中...',
|
|
||||||
deviceList: [],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.getDeviceData()
|
|
||||||
|
|
||||||
this.$adb.watch(() => {
|
|
||||||
this.getDeviceData()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleScreenUp(row) {
|
|
||||||
this.$adb.shell(row.id, 'input keyevent KEYCODE_POWER')
|
|
||||||
},
|
|
||||||
handleReset() {
|
|
||||||
this.$electron.ipcRenderer.send('restart-app')
|
|
||||||
},
|
|
||||||
async handleStart(row) {
|
|
||||||
row.$loading = true
|
|
||||||
try {
|
|
||||||
await this.$scrcpy.shell(`-s ${row.id}`)
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
if (error.message)
|
|
||||||
this.$message.warning(error.message)
|
|
||||||
}
|
|
||||||
row.$loading = false
|
|
||||||
},
|
|
||||||
async getDeviceData() {
|
|
||||||
this.loading = true
|
|
||||||
await sleep(500)
|
|
||||||
try {
|
|
||||||
const data = await this.$adb.getDevices()
|
|
||||||
this.deviceList = (data || [])
|
|
||||||
.filter(item => !isIPWithPort(item.id))
|
|
||||||
.map(item => ({
|
|
||||||
...item,
|
|
||||||
name: item.model ? item.model.split(':')[1] : '未授权设备',
|
|
||||||
$loading: false,
|
|
||||||
$unauthorized: item.type === 'unauthorized',
|
|
||||||
}))
|
|
||||||
console.log('getDeviceData.data', this.deviceList)
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
if (error.message)
|
|
||||||
this.$message.warning(error.message)
|
|
||||||
this.deviceList = []
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
this.loadingText = '正在获取设备列表...'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style></style>
|
|
@ -11,7 +11,7 @@ const app = createApp(App)
|
|||||||
app.use(plugins)
|
app.use(plugins)
|
||||||
|
|
||||||
app.config.globalProperties.$electron = window.electron
|
app.config.globalProperties.$electron = window.electron
|
||||||
app.config.globalProperties.$adb = window.adbkit()
|
app.config.globalProperties.$adb = window.adbkit
|
||||||
app.config.globalProperties.$scrcpy = window.scrcpy()
|
app.config.globalProperties.$scrcpy = window.scrcpy
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user