mirror of
https://github.com/viarotel-org/escrcpy.git
synced 2024-12-01 02:27:18 +01:00
feat: 🚀 新增支持添加设备备注
This commit is contained in:
parent
326a133460
commit
43f15be265
@ -4,7 +4,11 @@ module.exports = {
|
|||||||
'no-unused-vars': 'off',
|
'no-unused-vars': 'off',
|
||||||
'eqeqeq': 'off',
|
'eqeqeq': 'off',
|
||||||
'prefer-promise-reject-errors': 'off',
|
'prefer-promise-reject-errors': 'off',
|
||||||
|
|
||||||
'antfu/top-level-function': 'off',
|
'antfu/top-level-function': 'off',
|
||||||
|
|
||||||
'import/default': 'off',
|
'import/default': 'off',
|
||||||
|
|
||||||
|
'vue/no-mutating-props': 'off',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@
|
|||||||
|
|
||||||
- Adb 路径
|
- Adb 路径
|
||||||
- Scrcpy 路径
|
- Scrcpy 路径
|
||||||
- 文件存储路径(音视频及截图保存在这里)
|
- 文件存储路径(音视频录制及设备截图都保存在这里)
|
||||||
|
|
||||||
### 视频控制
|
### 视频控制
|
||||||
|
|
||||||
@ -98,7 +98,6 @@
|
|||||||
|
|
||||||
### 音视频录制
|
### 音视频录制
|
||||||
|
|
||||||
- 文件保存路径
|
|
||||||
- 录制视频格式
|
- 录制视频格式
|
||||||
|
|
||||||
### 音频控制
|
### 音频控制
|
||||||
|
@ -6,12 +6,18 @@ export default () => {
|
|||||||
'show-open-dialog',
|
'show-open-dialog',
|
||||||
async (event, { preset = '', ...options } = {}) => {
|
async (event, { preset = '', ...options } = {}) => {
|
||||||
// console.log('options', options)
|
// console.log('options', options)
|
||||||
try {
|
const res = await dialog
|
||||||
const res = await dialog.showOpenDialog(options)
|
.showOpenDialog(options)
|
||||||
// console.log('showOpenDialog.res', res)
|
.catch(e => console.warn(e))
|
||||||
|
|
||||||
if (res.canceled) {
|
if (res.canceled) {
|
||||||
return false
|
throw new Error('用户取消操作')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!res.filePaths.length) {
|
||||||
|
throw new Error('获取目录或文件路径失败')
|
||||||
|
}
|
||||||
|
|
||||||
const filePaths = res.filePaths
|
const filePaths = res.filePaths
|
||||||
|
|
||||||
switch (preset) {
|
switch (preset) {
|
||||||
@ -21,57 +27,37 @@ export default () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return filePaths
|
return filePaths
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.warn(error?.message || error)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
ipcMain.handle('open-path', async (event, pathValue) => {
|
ipcMain.handle('open-path', async (event, pathValue) => {
|
||||||
try {
|
return shell.openPath(pathValue)
|
||||||
await shell.openPath(pathValue)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.warn(error?.message || error)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle('show-item-in-folder', async (event, filePath) => {
|
ipcMain.handle('show-item-in-folder', async (event, filePath) => {
|
||||||
try {
|
return shell.showItemInFolder(filePath)
|
||||||
await shell.showItemInFolder(filePath)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.warn(error?.message || error)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
ipcMain.handle(
|
ipcMain.handle(
|
||||||
'show-save-dialog',
|
'show-save-dialog',
|
||||||
async (event, { filePath = '', ...options } = {}) => {
|
async (event, { filePath = '', ...options } = {}) => {
|
||||||
try {
|
const res = await dialog
|
||||||
const result = await dialog.showSaveDialog({
|
.showSaveDialog({
|
||||||
...options,
|
...options,
|
||||||
})
|
})
|
||||||
if (!result || result.canceled || !result.filePath) {
|
.catch(e => console.warn(e))
|
||||||
return false
|
|
||||||
|
if (res.canceled) {
|
||||||
|
throw new Error('用户取消操作')
|
||||||
}
|
}
|
||||||
|
|
||||||
const destinationPath = result.filePath
|
if (!res.filePath) {
|
||||||
|
throw new Error('获取文件路径失败')
|
||||||
|
}
|
||||||
|
|
||||||
|
const destinationPath = res.filePath
|
||||||
|
|
||||||
await fs.copy(filePath, destinationPath)
|
await fs.copy(filePath, destinationPath)
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error(error?.message || error)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,9 @@ import path from 'node:path'
|
|||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { Adb } from '@devicefarmer/adbkit'
|
import { Adb } from '@devicefarmer/adbkit'
|
||||||
|
import appStore from '@electron/helpers/store.js'
|
||||||
import { adbPath } from '@electron/configs/index.js'
|
import { adbPath } from '@electron/configs/index.js'
|
||||||
|
|
||||||
// console.log('adbPath', adbPath)
|
|
||||||
|
|
||||||
const exec = util.promisify(child_process.exec)
|
const exec = util.promisify(child_process.exec)
|
||||||
|
|
||||||
let client = null
|
let client = null
|
||||||
@ -18,6 +17,15 @@ window.addEventListener('beforeunload', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
appStore.onDidChange('scrcpy.adbPath', async (value) => {
|
||||||
|
console.log('onDidChange.scrcpy.adbPath.value', value)
|
||||||
|
if (client) {
|
||||||
|
await client.kill().catch(e => console.warn(e))
|
||||||
|
client = null
|
||||||
|
}
|
||||||
|
client = Adb.createClient({ bin: value })
|
||||||
|
})
|
||||||
|
|
||||||
const shell = async command => exec(`${adbPath} ${command}`)
|
const shell = async command => exec(`${adbPath} ${command}`)
|
||||||
const getDevices = async () => client.listDevicesWithPaths()
|
const getDevices = async () => client.listDevicesWithPaths()
|
||||||
const deviceShell = async (id, command) => client.getDevice(id).shell(command)
|
const deviceShell = async (id, command) => client.getDevice(id).shell(command)
|
||||||
@ -100,8 +108,8 @@ const watch = async (callback) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
client = Adb.createClient({ bin: adbPath })
|
client = Adb.createClient({ bin: appStore.get('scrcpy.adbPath') || adbPath })
|
||||||
// console.log('client', client)
|
console.log('client', client)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
shell,
|
shell,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
||||||
|
import store from '@electron/helpers/store.js'
|
||||||
import * as configs from '@electron/configs/index.js'
|
import * as configs from '@electron/configs/index.js'
|
||||||
import store from './store/index.js'
|
|
||||||
import electron from './electron/index.js'
|
import electron from './electron/index.js'
|
||||||
import adbkit from './adbkit/index.js'
|
import adbkit from './adbkit/index.js'
|
||||||
import scrcpy from './scrcpy/index.js'
|
import scrcpy from './scrcpy/index.js'
|
||||||
@ -10,7 +10,7 @@ export default {
|
|||||||
init(expose) {
|
init(expose) {
|
||||||
expose('nodePath', path)
|
expose('nodePath', path)
|
||||||
|
|
||||||
expose('appStore', store())
|
expose('appStore', store)
|
||||||
|
|
||||||
expose('electron', {
|
expose('electron', {
|
||||||
...electron(),
|
...electron(),
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { spawn } from 'node:child_process'
|
import { spawn } from 'node:child_process'
|
||||||
|
import appStore from '@electron/helpers/store.js'
|
||||||
import { adbPath, scrcpyPath } from '@electron/configs/index.js'
|
import { adbPath, scrcpyPath } from '@electron/configs/index.js'
|
||||||
|
|
||||||
const shell = async (command, { stdout, stderr } = {}) => {
|
const shell = async (command, { stdout, stderr } = {}) => {
|
||||||
const args = command.split(' ')
|
const args = command.split(' ')
|
||||||
const scrcpyProcess = spawn(scrcpyPath, args, {
|
const scrcpyProcess = spawn(
|
||||||
|
appStore.get('scrcpy.scrcpyPath') || scrcpyPath,
|
||||||
|
args,
|
||||||
|
{
|
||||||
env: { ...process.env, ADB: adbPath },
|
env: { ...process.env, ADB: adbPath },
|
||||||
shell: true,
|
shell: true,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
scrcpyProcess.stdout.on('data', (data) => {
|
scrcpyProcess.stdout.on('data', (data) => {
|
||||||
const stringData = data.toString()
|
const stringData = data.toString()
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
import Store from 'electron-store'
|
|
||||||
import { createProxy } from '@electron/helpers/index'
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
const appStore = new Store()
|
|
||||||
|
|
||||||
appStore.onDidAnyChange(() => {
|
|
||||||
console.log('reload.appStore.onDidAnyChange', appStore.store)
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
...createProxy(appStore, [
|
|
||||||
'set',
|
|
||||||
'get',
|
|
||||||
'delete',
|
|
||||||
'clear',
|
|
||||||
'reset',
|
|
||||||
'has',
|
|
||||||
'onDidChange',
|
|
||||||
'onDidAnyChange',
|
|
||||||
'openInEditor',
|
|
||||||
]),
|
|
||||||
...appStore,
|
|
||||||
getAll: () => appStore.store,
|
|
||||||
setAll: value => (appStore.store = value),
|
|
||||||
}
|
|
||||||
}
|
|
25
electron/helpers/store.js
Normal file
25
electron/helpers/store.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import Store from 'electron-store'
|
||||||
|
import { createProxy } from './index.js'
|
||||||
|
|
||||||
|
const appStore = new Store()
|
||||||
|
|
||||||
|
appStore.onDidAnyChange(() => {
|
||||||
|
console.log('appStore.onDidAnyChange', appStore.store)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default {
|
||||||
|
...createProxy(appStore, [
|
||||||
|
'set',
|
||||||
|
'get',
|
||||||
|
'delete',
|
||||||
|
'clear',
|
||||||
|
'reset',
|
||||||
|
'has',
|
||||||
|
'onDidChange',
|
||||||
|
'onDidAnyChange',
|
||||||
|
'openInEditor',
|
||||||
|
]),
|
||||||
|
...appStore,
|
||||||
|
getAll: () => appStore.store,
|
||||||
|
setAll: value => (appStore.store = value),
|
||||||
|
}
|
@ -1,17 +1,15 @@
|
|||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import { BrowserWindow, app, shell } from 'electron'
|
import { BrowserWindow, app, shell } from 'electron'
|
||||||
import Store from 'electron-store'
|
|
||||||
import { electronApp, optimizer } from '@electron-toolkit/utils'
|
import { electronApp, optimizer } from '@electron-toolkit/utils'
|
||||||
|
|
||||||
// packaged.js 必须位于非依赖项的顶部
|
// packaged.js 必须位于非依赖项的顶部
|
||||||
import './helpers/packaged.js'
|
import './helpers/packaged.js'
|
||||||
|
import './helpers/store.js'
|
||||||
|
|
||||||
import { icnsLogoPath, icoLogoPath, logoPath } from './configs/index.js'
|
import { icnsLogoPath, icoLogoPath, logoPath } from './configs/index.js'
|
||||||
|
|
||||||
import events from './events/index.js'
|
import events from './events/index.js'
|
||||||
|
|
||||||
const appStore = new Store()
|
|
||||||
|
|
||||||
// The built directory structure
|
// The built directory structure
|
||||||
//
|
//
|
||||||
// ├─┬─┬ dist
|
// ├─┬─┬ dist
|
||||||
|
22
src/App.vue
22
src/App.vue
@ -8,7 +8,7 @@
|
|||||||
:name="item.prop"
|
:name="item.prop"
|
||||||
lazy
|
lazy
|
||||||
>
|
>
|
||||||
<component :is="item.prop" :ref="item.prop" />
|
<component :is="item.prop" v-if="isRender(item)" :ref="item.prop" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
@ -42,13 +42,31 @@ export default {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
activeTab: 'Device',
|
activeTab: 'Device',
|
||||||
|
rendered: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$store.scrcpy.init()
|
this.$store.scrcpy.init()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onTabChange(prop) {},
|
isRender(item) {
|
||||||
|
if (this.activeTab === item.prop) {
|
||||||
|
return this.rendered
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
async reRender() {
|
||||||
|
this.rendered = false
|
||||||
|
await this.$nextTick()
|
||||||
|
this.rendered = true
|
||||||
|
},
|
||||||
|
async onTabChange(prop) {
|
||||||
|
switch (prop) {
|
||||||
|
case 'Device':
|
||||||
|
this.reRender()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -84,13 +84,19 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async handleInstall(device) {
|
async handleInstall(device) {
|
||||||
const files = await this.$electron.ipcRenderer.invoke(
|
let files = null
|
||||||
'show-open-dialog',
|
|
||||||
{
|
try {
|
||||||
|
files = await this.$electron.ipcRenderer.invoke('show-open-dialog', {
|
||||||
properties: ['openFile', 'multiSelections'],
|
properties: ['openFile', 'multiSelections'],
|
||||||
filters: [{ name: '请选择要安装的应用', extensions: ['apk'] }],
|
filters: [{ name: '请选择要安装的应用', extensions: ['apk'] }],
|
||||||
},
|
})
|
||||||
)
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (error.message) {
|
||||||
|
this.$message.warning(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!files) {
|
if (!files) {
|
||||||
return false
|
return false
|
||||||
@ -174,7 +180,10 @@ export default {
|
|||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
type: 'success',
|
type: 'success',
|
||||||
})
|
})
|
||||||
this.$electron.ipcRenderer.invoke('show-item-in-folder', savePath)
|
await this.$electron.ipcRenderer.invoke(
|
||||||
|
'show-item-in-folder',
|
||||||
|
savePath,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
if (error.message) {
|
if (error.message) {
|
||||||
|
55
src/components/Device/Remark/index.vue
Normal file
55
src/components/Device/Remark/index.vue
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<el-popover
|
||||||
|
placement="bottom-start"
|
||||||
|
:width="250"
|
||||||
|
trigger="hover"
|
||||||
|
@show="handleFocus"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<el-tag effect="light" class="ml-2 cursor-pointer">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<el-icon>
|
||||||
|
<EditPen />
|
||||||
|
</el-icon>
|
||||||
|
<span class="pl-1">{{ device.$remark || "备注" }}</span>
|
||||||
|
</div>
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-input
|
||||||
|
ref="elInput"
|
||||||
|
v-model="device.$remark"
|
||||||
|
class=""
|
||||||
|
placeholder="请输入设备备注"
|
||||||
|
clearable
|
||||||
|
@change="onChange"
|
||||||
|
></el-input>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
device: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
created() {},
|
||||||
|
methods: {
|
||||||
|
onChange(value) {
|
||||||
|
// console.log('onChange', value)
|
||||||
|
this.$store.device.setRemark(this.device.id, value)
|
||||||
|
},
|
||||||
|
async handleFocus() {
|
||||||
|
console.log('handleFocus')
|
||||||
|
this.$refs.elInput.focus()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
@ -63,6 +63,7 @@
|
|||||||
label="设备 ID"
|
label="设备 ID"
|
||||||
show-overflow-tooltip
|
show-overflow-tooltip
|
||||||
align="left"
|
align="left"
|
||||||
|
width="200"
|
||||||
/>
|
/>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="name"
|
prop="name"
|
||||||
@ -84,13 +85,15 @@
|
|||||||
|
|
||||||
{{ row.name }}
|
{{ row.name }}
|
||||||
|
|
||||||
<el-tag v-if="row.$wireless" effect="light" class="ml-2">
|
<el-tag v-if="row.$wifi" effect="light" class="ml-2">
|
||||||
WIFI
|
WIFI
|
||||||
</el-tag>
|
</el-tag>
|
||||||
|
|
||||||
|
<Remark :device="row" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="500" align="left">
|
<el-table-column label="操作" width="400" align="left">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
@ -115,7 +118,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
v-if="!row.$wireless"
|
v-if="!row.$wifi"
|
||||||
type="primary"
|
type="primary"
|
||||||
text
|
text
|
||||||
:disabled="
|
:disabled="
|
||||||
@ -130,7 +133,7 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
v-if="row.$wireless"
|
v-if="row.$wifi"
|
||||||
type="danger"
|
type="danger"
|
||||||
text
|
text
|
||||||
:loading="row.$stopLoading"
|
:loading="row.$stopLoading"
|
||||||
@ -162,6 +165,7 @@
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import PairDialog from './PairDialog/index.vue'
|
import PairDialog from './PairDialog/index.vue'
|
||||||
import ControlBar from './ControlBar/index.vue'
|
import ControlBar from './ControlBar/index.vue'
|
||||||
|
import Remark from './Remark/index.vue'
|
||||||
import storage from '@/utils/storages'
|
import storage from '@/utils/storages'
|
||||||
import { isIPWithPort, sleep } from '@/utils/index.js'
|
import { isIPWithPort, sleep } from '@/utils/index.js'
|
||||||
|
|
||||||
@ -169,6 +173,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
PairDialog,
|
PairDialog,
|
||||||
ControlBar,
|
ControlBar,
|
||||||
|
Remark,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const adbCache = storage.get('adbCache') || {}
|
const adbCache = storage.get('adbCache') || {}
|
||||||
@ -191,13 +196,15 @@ export default {
|
|||||||
return this.$store.scrcpy.stringConfig
|
return this.$store.scrcpy.stringConfig
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
created() {
|
async created() {
|
||||||
this.getDeviceData()
|
this.getDeviceData()
|
||||||
|
|
||||||
this.$adb.watch(async (type, ret) => {
|
this.unAdbWatch = await this.$adb.watch(async (type, ret) => {
|
||||||
console.log('adb.watch.ret', ret)
|
console.log('adb.watch.ret', ret)
|
||||||
|
|
||||||
|
if (ret && ret.id) {
|
||||||
this.getDeviceData()
|
this.getDeviceData()
|
||||||
|
}
|
||||||
|
|
||||||
if (type === 'add' && !isIPWithPort(ret.id) && ret.$host) {
|
if (type === 'add' && !isIPWithPort(ret.id) && ret.$host) {
|
||||||
this.formData = {
|
this.formData = {
|
||||||
@ -207,6 +214,11 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
if (this.unAdbWatch) {
|
||||||
|
this.unAdbWatch()
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onStdout() {},
|
onStdout() {},
|
||||||
toggleRowExpansion(...params) {
|
toggleRowExpansion(...params) {
|
||||||
@ -242,7 +254,10 @@ export default {
|
|||||||
type: 'success',
|
type: 'success',
|
||||||
})
|
})
|
||||||
|
|
||||||
this.$electron.ipcRenderer.invoke('show-item-in-folder', savePath)
|
await this.$electron.ipcRenderer.invoke(
|
||||||
|
'show-item-in-folder',
|
||||||
|
savePath,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
if (error.message) {
|
if (error.message) {
|
||||||
@ -362,15 +377,16 @@ export default {
|
|||||||
$recordLoading: false,
|
$recordLoading: false,
|
||||||
$stopLoading: false,
|
$stopLoading: false,
|
||||||
$unauthorized: item.type === 'unauthorized',
|
$unauthorized: item.type === 'unauthorized',
|
||||||
$wireless: isIPWithPort(item.id),
|
$wifi: isIPWithPort(item.id),
|
||||||
|
$remark: this.$store.device.getRemark(item.id),
|
||||||
})) || []
|
})) || []
|
||||||
|
|
||||||
console.log('getDeviceData.data', this.deviceList)
|
console.log('getDeviceData.data', this.deviceList)
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.log(error)
|
console.warn(error)
|
||||||
if (error.message) {
|
if (error?.message || error?.cause?.message) {
|
||||||
this.$message.warning(error.message)
|
this.$message.warning(error?.message || error?.cause?.message)
|
||||||
}
|
}
|
||||||
this.deviceList = []
|
this.deviceList = []
|
||||||
}
|
}
|
||||||
|
@ -90,19 +90,24 @@
|
|||||||
<el-input
|
<el-input
|
||||||
v-if="item_1.type === 'input.path'"
|
v-if="item_1.type === 'input.path'"
|
||||||
v-bind="item_1.props || {}"
|
v-bind="item_1.props || {}"
|
||||||
:value="scrcpyForm[item_1.field]"
|
v-model="scrcpyForm[item_1.field]"
|
||||||
readonly
|
|
||||||
class="!w-full"
|
class="!w-full"
|
||||||
clearable
|
clearable
|
||||||
:placeholder="item_1.placeholder"
|
:placeholder="item_1.placeholder"
|
||||||
:title="item_1.placeholder"
|
:title="item_1.placeholder"
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<el-button
|
||||||
|
icon="Search"
|
||||||
@click="
|
@click="
|
||||||
handleSelect(item_1, {
|
handleSelect(item_1, {
|
||||||
properties: item_1.properties,
|
properties: item_1.properties,
|
||||||
filters: item_1.filters,
|
filters: item_1.filters,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
></el-input>
|
/>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
<el-switch
|
<el-switch
|
||||||
v-if="item_1.type === 'switch'"
|
v-if="item_1.type === 'switch'"
|
||||||
v-bind="item_1.props || {}"
|
v-bind="item_1.props || {}"
|
||||||
@ -193,22 +198,22 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async handleImport() {
|
async handleImport() {
|
||||||
const result = await this.$electron.ipcRenderer.invoke(
|
try {
|
||||||
'show-open-dialog',
|
await this.$electron.ipcRenderer.invoke('show-open-dialog', {
|
||||||
{
|
|
||||||
preset: 'replaceFile',
|
preset: 'replaceFile',
|
||||||
filePath: this.$appStore.path,
|
filePath: this.$appStore.path,
|
||||||
filters: [{ name: '请选择要导入的配置文件', extensions: ['json'] }],
|
filters: [{ name: '请选择要导入的配置文件', extensions: ['json'] }],
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
this.$message.warning('导入偏好配置失败')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$message.success('导入偏好配置成功')
|
this.$message.success('导入偏好配置成功')
|
||||||
|
|
||||||
this.scrcpyForm = this.$store.scrcpy.init()
|
this.scrcpyForm = this.$store.scrcpy.init()
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (error.message) {
|
||||||
|
this.$message.warning(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleEdit() {
|
handleEdit() {
|
||||||
this.$appStore.openInEditor()
|
this.$appStore.openInEditor()
|
||||||
@ -220,40 +225,47 @@ export default {
|
|||||||
duration: 0,
|
duration: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
const result = await this.$electron.ipcRenderer.invoke(
|
try {
|
||||||
'show-save-dialog',
|
await this.$electron.ipcRenderer.invoke('show-save-dialog', {
|
||||||
{
|
|
||||||
defaultPath: 'escrcpy-configs.json',
|
defaultPath: 'escrcpy-configs.json',
|
||||||
filePath: this.$appStore.path,
|
filePath: this.$appStore.path,
|
||||||
filters: [
|
filters: [
|
||||||
{ name: '请选择配置文件要保存的位置', extensions: ['json'] },
|
{ name: '请选择配置文件要保存的位置', extensions: ['json'] },
|
||||||
],
|
],
|
||||||
},
|
})
|
||||||
)
|
|
||||||
|
|
||||||
messageEl.close()
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
this.$message.success('导出偏好配置成功')
|
this.$message.success('导出偏好配置成功')
|
||||||
}
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (error.message) {
|
||||||
|
this.$message.warning(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messageEl.close()
|
||||||
},
|
},
|
||||||
async handleSelect({ field }, { properties, filters } = {}) {
|
async handleSelect({ field }, { properties, filters } = {}) {
|
||||||
const res = await this.$electron.ipcRenderer.invoke('show-open-dialog', {
|
try {
|
||||||
|
const files = await this.$electron.ipcRenderer.invoke(
|
||||||
|
'show-open-dialog',
|
||||||
|
{
|
||||||
properties,
|
properties,
|
||||||
filters,
|
filters,
|
||||||
defaultPath: this.scrcpyForm[field],
|
defaultPath: this.scrcpyForm[field],
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
if (!res) {
|
const value = files[0]
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const value = res[0]
|
|
||||||
|
|
||||||
this.scrcpyForm[field] = value
|
this.scrcpyForm[field] = value
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (error.message) {
|
||||||
|
this.$message.warning(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
handleSave() {
|
handleSave() {
|
||||||
this.$store.scrcpy.updateConfig(this.scrcpyForm)
|
this.$store.scrcpy.setConfig(this.scrcpyForm)
|
||||||
this.$message.success('保存配置成功,将在下一次控制设备时生效')
|
this.$message.success('保存配置成功,将在下一次控制设备时生效')
|
||||||
},
|
},
|
||||||
getSubModel(type) {
|
getSubModel(type) {
|
||||||
@ -265,7 +277,7 @@ export default {
|
|||||||
...this.scrcpyForm,
|
...this.scrcpyForm,
|
||||||
...this.$store.scrcpy.getDefaultConfig(type),
|
...this.$store.scrcpy.getDefaultConfig(type),
|
||||||
}
|
}
|
||||||
this.$store.scrcpy.updateConfig(this.scrcpyForm)
|
this.$store.scrcpy.setConfig(this.scrcpyForm)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
37
src/store/device/index.js
Normal file
37
src/store/device/index.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
|
const $appStore = window.appStore
|
||||||
|
|
||||||
|
const removeDot = value => value.replaceAll('.', '_')
|
||||||
|
|
||||||
|
export const useDeviceStore = defineStore({
|
||||||
|
id: 'app-device',
|
||||||
|
state() {
|
||||||
|
return {
|
||||||
|
config: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getters: {},
|
||||||
|
actions: {
|
||||||
|
removeDot,
|
||||||
|
init() {
|
||||||
|
this.config = {
|
||||||
|
...($appStore.get('device') || {}),
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.config
|
||||||
|
},
|
||||||
|
setConfig(value, key = 'device') {
|
||||||
|
$appStore.set(key, value)
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
setRemark(deviceId, value) {
|
||||||
|
$appStore.set(`device.${removeDot(deviceId)}.remark`, value)
|
||||||
|
this.init()
|
||||||
|
},
|
||||||
|
getRemark(deviceId) {
|
||||||
|
const value = $appStore.get(`device.${removeDot(deviceId)}.remark`)
|
||||||
|
return value
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
@ -1,7 +1,8 @@
|
|||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
import { useScrcpyStore } from './scrcpy/index.js'
|
import { useScrcpyStore } from './scrcpy/index.js'
|
||||||
|
import { useDeviceStore } from './device/index.js'
|
||||||
|
|
||||||
export { useScrcpyStore }
|
export { useScrcpyStore, useDeviceStore }
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
install(app) {
|
install(app) {
|
||||||
@ -10,6 +11,7 @@ export default {
|
|||||||
app.use(store)
|
app.use(store)
|
||||||
app.config.globalProperties.$store = {
|
app.config.globalProperties.$store = {
|
||||||
scrcpy: useScrcpyStore(),
|
scrcpy: useScrcpyStore(),
|
||||||
|
device: useDeviceStore(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ export const useScrcpyStore = defineStore({
|
|||||||
}, [])
|
}, [])
|
||||||
.join(' ')
|
.join(' ')
|
||||||
|
|
||||||
console.log('stringifyConfig.value', value)
|
// console.log('stringifyConfig.value', value)
|
||||||
|
|
||||||
return value
|
return value
|
||||||
},
|
},
|
||||||
@ -79,10 +79,10 @@ export const useScrcpyStore = defineStore({
|
|||||||
|
|
||||||
return this.config
|
return this.config
|
||||||
},
|
},
|
||||||
updateConfig(data) {
|
setConfig(data) {
|
||||||
const pickConfig = pickBy(data, value => !!value)
|
const pickConfig = pickBy(data, value => !!value)
|
||||||
|
|
||||||
console.log('pickConfig', pickConfig)
|
// console.log('pickConfig', pickConfig)
|
||||||
|
|
||||||
$appStore.set('scrcpy', pickConfig)
|
$appStore.set('scrcpy', pickConfig)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user