mirror of
https://github.com/viarotel-org/escrcpy.git
synced 2024-11-14 18:57:40 +01:00
refactor: 🔨 对偏好设置存储规则逻辑代码进行重构以便于添加更多功能
This commit is contained in:
parent
054c55b26d
commit
517eecd2e1
@ -4,6 +4,7 @@ module.exports = {
|
||||
'no-unused-vars': 'off',
|
||||
'eqeqeq': 'off',
|
||||
'prefer-promise-reject-errors': 'off',
|
||||
'no-new-func': 'off',
|
||||
|
||||
'antfu/top-level-function': 'off',
|
||||
|
||||
|
@ -18,8 +18,8 @@ window.addEventListener('beforeunload', () => {
|
||||
}
|
||||
})
|
||||
|
||||
appStore.onDidChange('scrcpy.global.adbPath', async (value, oldValue) => {
|
||||
console.log('onDidChange.scrcpy.global.adbPath', value)
|
||||
appStore.onDidChange('scrcpy.common.adbPath', async (value, oldValue) => {
|
||||
console.log('onDidChange.scrcpy.common.adbPath', value)
|
||||
|
||||
if (value === oldValue) {
|
||||
return false
|
||||
@ -146,7 +146,7 @@ const watch = async (callback) => {
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const binPath = appStore.get('scrcpy.global.adbPath') || adbPath
|
||||
const binPath = appStore.get('scrcpy.common.adbPath') || adbPath
|
||||
|
||||
client = Adb.createClient({
|
||||
bin: binPath,
|
||||
|
@ -3,8 +3,8 @@ import appStore from '@electron/helpers/store.js'
|
||||
import { adbPath, scrcpyPath } from '@electron/configs/index.js'
|
||||
|
||||
const shell = async (command, { stdout, stderr } = {}) => {
|
||||
const spawnPath = appStore.get('scrcpy.global.scrcpyPath') || scrcpyPath
|
||||
const ADB = appStore.get('scrcpy.global.adbPath') || adbPath
|
||||
const spawnPath = appStore.get('scrcpy.common.scrcpyPath') || scrcpyPath
|
||||
const ADB = appStore.get('scrcpy.common.adbPath') || adbPath
|
||||
const args = command.split(' ')
|
||||
|
||||
const scrcpyProcess = spawn(`"${spawnPath}"`, args, {
|
||||
|
@ -29,7 +29,7 @@ export default {
|
||||
return {
|
||||
tabsModel: [
|
||||
{
|
||||
label: this.$t('devices.name'),
|
||||
label: this.$t('device.list'),
|
||||
prop: 'Device',
|
||||
},
|
||||
{
|
||||
@ -47,7 +47,7 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$store.scrcpy.init()
|
||||
this.$store.preference.init()
|
||||
this.showTips()
|
||||
},
|
||||
methods: {
|
||||
|
@ -17,7 +17,7 @@
|
||||
>
|
||||
{{
|
||||
loading && percent
|
||||
? `${$t("about.updating")}...(${percent.toFixed(1)}%)`
|
||||
? `${$t("about.update.progress")}...(${percent.toFixed(1)}%)`
|
||||
: $t("about.update")
|
||||
}}
|
||||
</el-button>
|
||||
|
@ -36,46 +36,46 @@ export default {
|
||||
return {
|
||||
controlModel: [
|
||||
{
|
||||
label: this.$t('devices.operates.switch'),
|
||||
label: this.$t('device.operates.switch'),
|
||||
elIcon: 'Switch',
|
||||
command: 'input keyevent KEYCODE_APP_SWITCH',
|
||||
},
|
||||
{
|
||||
label: this.$t('devices.operates.home'),
|
||||
label: this.$t('device.operates.home'),
|
||||
elIcon: 'HomeFilled',
|
||||
command: 'input keyevent KEYCODE_HOME',
|
||||
},
|
||||
{
|
||||
label: this.$t('devices.operates.return'),
|
||||
label: this.$t('device.operates.return'),
|
||||
elIcon: 'Back',
|
||||
command: 'input keyevent KEYCODE_BACK',
|
||||
},
|
||||
{
|
||||
label: this.$t('devices.operates.notification'),
|
||||
label: this.$t('device.operates.notification'),
|
||||
elIcon: 'Notification',
|
||||
command: 'cmd statusbar expand-notifications',
|
||||
tips: '打开下拉菜单选项',
|
||||
},
|
||||
{
|
||||
label: this.$t('devices.operates.power'),
|
||||
label: this.$t('device.operates.power'),
|
||||
elIcon: 'SwitchButton',
|
||||
command: 'input keyevent KEYCODE_POWER',
|
||||
tips: '可以用来开启或关闭屏幕',
|
||||
},
|
||||
{
|
||||
label: this.$t('devices.operates.reboot'),
|
||||
label: this.$t('device.operates.reboot'),
|
||||
elIcon: 'RefreshLeft',
|
||||
command: 'reboot',
|
||||
tips: '可以用来开启或关闭屏幕',
|
||||
},
|
||||
{
|
||||
label: this.$t('devices.operates.capture'),
|
||||
label: this.$t('device.operates.capture'),
|
||||
elIcon: 'Crop',
|
||||
handle: this.handleScreenCap,
|
||||
tips: '',
|
||||
},
|
||||
{
|
||||
label: this.$t('devices.operates.install'),
|
||||
label: this.$t('device.operates.install'),
|
||||
svgIcon: 'install',
|
||||
handle: this.handleInstall,
|
||||
tips: '',
|
||||
@ -85,8 +85,8 @@ export default {
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
scrcpyConfig(...args) {
|
||||
return this.$store.scrcpy.getConfig(...args)
|
||||
preferenceData(...args) {
|
||||
return this.$store.preference.getData(...args)
|
||||
},
|
||||
async handleInstall(device) {
|
||||
let files = null
|
||||
@ -166,7 +166,7 @@ export default {
|
||||
'YYYY-MM-DD-HH-mm-ss',
|
||||
)}.png`
|
||||
|
||||
const deviceConfig = this.scrcpyConfig(device.id)
|
||||
const deviceConfig = this.preferenceData(device.id)
|
||||
const savePath = this.$path.resolve(deviceConfig.savePath, fileName)
|
||||
|
||||
try {
|
||||
|
@ -12,7 +12,7 @@
|
||||
<EditPen />
|
||||
</el-icon>
|
||||
<span class="pl-1">{{
|
||||
device.$remark || $t("devices.device.remark")
|
||||
device.$remark || $t("device.remark")
|
||||
}}</span>
|
||||
</div>
|
||||
</el-tag>
|
||||
|
@ -8,7 +8,7 @@
|
||||
clearable
|
||||
>
|
||||
<template #prepend>
|
||||
{{ $t("devices.wireless.name") }}
|
||||
{{ $t("device.wireless.name") }}
|
||||
</template>
|
||||
</el-input>
|
||||
<div class="text-gray-500 text-sm">
|
||||
@ -30,7 +30,7 @@
|
||||
:loading="connectLoading"
|
||||
@click="handleConnect"
|
||||
>
|
||||
{{ $t("devices.wireless.connect.name") }}
|
||||
{{ $t("device.wireless.connect.name") }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@ -38,13 +38,13 @@
|
||||
:loading="loading"
|
||||
@click="handleRefresh"
|
||||
>
|
||||
{{ $t("devices.refresh.name") }}
|
||||
{{ $t("device.refresh.name") }}
|
||||
</el-button>
|
||||
<el-button type="warning" icon="RefreshRight" @click="handleRestart">
|
||||
{{ $t("devices.restart.name") }}
|
||||
{{ $t("device.restart.name") }}
|
||||
</el-button>
|
||||
<el-button icon="View" @click="handleLog">
|
||||
{{ $t("devices.log.name") }}
|
||||
{{ $t("device.log.name") }}
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="pt-4 flex-1 h-0 overflow-hidden">
|
||||
@ -59,17 +59,17 @@
|
||||
row-key="id"
|
||||
>
|
||||
<template #empty>
|
||||
<el-empty :description="$t('devices.empty')" />
|
||||
<el-empty :description="$t('device.list.empty')" />
|
||||
</template>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
:label="$t('devices.device.id')"
|
||||
:label="$t('device.id')"
|
||||
show-overflow-tooltip
|
||||
align="left"
|
||||
width="200"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('devices.device.name')"
|
||||
:label="$t('device.name')"
|
||||
show-overflow-tooltip
|
||||
align="left"
|
||||
>
|
||||
@ -77,7 +77,7 @@
|
||||
<div class="flex items-center">
|
||||
<el-tooltip
|
||||
v-if="row.$unauthorized"
|
||||
:content="$t('devices.device.permission.error')"
|
||||
:content="$t('device.permission.error')"
|
||||
placement="top-start"
|
||||
>
|
||||
<el-icon class="mr-1 text-red-600 text-lg">
|
||||
@ -98,7 +98,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('devices.operates.name')"
|
||||
:label="$t('device.operates.name')"
|
||||
width="450"
|
||||
align="left"
|
||||
>
|
||||
@ -113,8 +113,8 @@
|
||||
>
|
||||
{{
|
||||
row.$loading
|
||||
? $t("devices.mirror.progress")
|
||||
: $t("devices.mirror.start")
|
||||
? $t("device.mirror.progress")
|
||||
: $t("device.mirror.start")
|
||||
}}
|
||||
</el-button>
|
||||
|
||||
@ -128,8 +128,8 @@
|
||||
>
|
||||
{{
|
||||
row.$recordLoading
|
||||
? $t("devices.record.progress")
|
||||
: $t("devices.record.start")
|
||||
? $t("device.record.progress")
|
||||
: $t("device.record.start")
|
||||
}}
|
||||
</el-button>
|
||||
|
||||
@ -145,7 +145,7 @@
|
||||
<template #icon>
|
||||
<svg-icon name="wifi"></svg-icon>
|
||||
</template>
|
||||
{{ $t("devices.wireless.mode") }}
|
||||
{{ $t("device.wireless.mode") }}
|
||||
</el-button>
|
||||
|
||||
<el-button
|
||||
@ -159,15 +159,15 @@
|
||||
>
|
||||
{{
|
||||
row.$stopLoading
|
||||
? $t("devices.wireless.disconnect.progress")
|
||||
: $t("devices.wireless.disconnect.start")
|
||||
? $t("device.wireless.disconnect.progress")
|
||||
: $t("device.wireless.disconnect.start")
|
||||
}}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column type="expand">
|
||||
<template #header>
|
||||
<el-icon class="" :title="$t('devices.operates.more')">
|
||||
<el-icon class="" :title="$t('device.operates.more')">
|
||||
<Operation class="" />
|
||||
</el-icon>
|
||||
</template>
|
||||
@ -199,7 +199,7 @@ export default {
|
||||
const adbCache = storage.get('adbCache') || {}
|
||||
return {
|
||||
loading: false,
|
||||
loadingText: this.$t('devices.loading'),
|
||||
loadingText: this.$t('device.list.loading'),
|
||||
connectLoading: false,
|
||||
deviceList: [],
|
||||
formData: {
|
||||
@ -233,11 +233,11 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
scrcpyConfig(...args) {
|
||||
return this.$store.scrcpy.getConfig(...args)
|
||||
preferenceData(...args) {
|
||||
return this.$store.preference.getData(...args)
|
||||
},
|
||||
scrcpyArgs(...args) {
|
||||
return this.$store.scrcpy.getStringConfig(...args)
|
||||
return this.$store.preference.getScrcpyData(...args)
|
||||
},
|
||||
handleRefresh() {
|
||||
this.getDeviceData({ resetResolve: true })
|
||||
@ -246,24 +246,24 @@ export default {
|
||||
try {
|
||||
await this.$confirm(
|
||||
`
|
||||
<div>${this.$t('devices.reset.reasons[0]')}</div>
|
||||
<div class="text-red-500">${this.$t('devices.reset.reasons[1]')}</div>
|
||||
<div>${this.$t('device.reset.reasons[0]')}</div>
|
||||
<div class="text-red-500">${this.$t('device.reset.reasons[1]')}</div>
|
||||
`,
|
||||
this.$t('devices.reset.title'),
|
||||
this.$t('device.reset.title'),
|
||||
{
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: this.$t('devices.reset.confirm'),
|
||||
cancelButtonText: this.$t('devices.reset.cancel'),
|
||||
confirmButtonText: this.$t('device.reset.confirm'),
|
||||
cancelButtonText: this.$t('device.reset.cancel'),
|
||||
closeOnClickModal: false,
|
||||
type: 'warning',
|
||||
},
|
||||
)
|
||||
|
||||
this.$store.scrcpy.resetDeps(depType)
|
||||
this.$store.preference.resetDeps(depType)
|
||||
|
||||
this.$root.reRender('Preference')
|
||||
|
||||
this.$message.success(this.$t('devices.reset.success'))
|
||||
this.$message.success(this.$t('device.reset.success'))
|
||||
}
|
||||
catch (error) {
|
||||
if (error.message) {
|
||||
@ -276,7 +276,7 @@ export default {
|
||||
this.$refs.elTable.toggleRowExpansion(...params)
|
||||
},
|
||||
getRecordPath(row) {
|
||||
const rowConfig = this.scrcpyConfig(row.id)
|
||||
const rowConfig = this.preferenceData(row.id)
|
||||
const basePath = rowConfig.savePath
|
||||
const recordFormat = rowConfig['--record-format']
|
||||
|
||||
@ -301,7 +301,7 @@ export default {
|
||||
const command = `--serial=${row.id} --window-title=${
|
||||
row.$remark ? `${row.$remark}-` : ''
|
||||
}${row.$name}-${row.id}-🎥${this.$t(
|
||||
'devices.record.progress',
|
||||
'device.record.progress',
|
||||
)}... --record=${savePath} ${this.scrcpyArgs(row.id)}`
|
||||
|
||||
console.log('handleRecord.command', command)
|
||||
@ -309,8 +309,8 @@ export default {
|
||||
await this.$scrcpy.shell(command, { stdout: this.onStdout })
|
||||
|
||||
await this.$confirm(
|
||||
this.$t('devices.record.success.message'),
|
||||
this.$t('devices.record.success.title'),
|
||||
this.$t('device.record.success.message'),
|
||||
this.$t('device.record.success.title'),
|
||||
{
|
||||
confirmButtonText: this.$t('common.confirm'),
|
||||
cancelButtonText: this.$t('common.cancel'),
|
||||
@ -379,7 +379,7 @@ export default {
|
||||
async handleConnect() {
|
||||
if (!this.formData.host) {
|
||||
this.$message.warning(
|
||||
this.$t('devices.wireless.connect.error.no-address'),
|
||||
this.$t('device.wireless.connect.error.no-address'),
|
||||
)
|
||||
return false
|
||||
}
|
||||
@ -387,7 +387,7 @@ export default {
|
||||
this.connectLoading = true
|
||||
try {
|
||||
await this.$adb.connect(this.formData.host, this.formData.port || 5555)
|
||||
this.$message.success(this.$t('devices.wireless.connect.success'))
|
||||
this.$message.success(this.$t('device.wireless.connect.success'))
|
||||
storage.set('adbCache', this.formData)
|
||||
}
|
||||
catch (error) {
|
||||
@ -400,23 +400,21 @@ export default {
|
||||
await this.$confirm(
|
||||
`
|
||||
<div class="pb-4 text-sm text-red-500">${this.$t(
|
||||
'devices.wireless.connect.error.detail',
|
||||
'device.wireless.connect.error.detail',
|
||||
)}:${message}</div>
|
||||
<div>${this.$t('devices.wireless.connect.error.reasons[0]')}:</div>
|
||||
<div>1. ${this.$t('devices.wireless.connect.error.reasons[1]')} </div>
|
||||
<div>2. ${this.$t('devices.wireless.connect.error.reasons[2]')} </div>
|
||||
<div>3. ${this.$t('devices.wireless.connect.error.reasons[3]')} </div>
|
||||
<div>4. ${this.$t('devices.wireless.connect.error.reasons[4]')} </div>
|
||||
<div>5. ${this.$t('devices.wireless.connect.error.reasons[5]')} </div>
|
||||
<div>${this.$t('device.wireless.connect.error.reasons[0]')}:</div>
|
||||
<div>1. ${this.$t('device.wireless.connect.error.reasons[1]')} </div>
|
||||
<div>2. ${this.$t('device.wireless.connect.error.reasons[2]')} </div>
|
||||
<div>3. ${this.$t('device.wireless.connect.error.reasons[3]')} </div>
|
||||
<div>4. ${this.$t('device.wireless.connect.error.reasons[4]')} </div>
|
||||
<div>5. ${this.$t('device.wireless.connect.error.reasons[5]')} </div>
|
||||
`,
|
||||
this.$t('devices.wireless.connect.error.title'),
|
||||
this.$t('device.wireless.connect.error.title'),
|
||||
{
|
||||
dangerouslyUseHTMLString: true,
|
||||
closeOnClickModal: false,
|
||||
confirmButtonText: this.$t(
|
||||
'devices.wireless.connect.error.confirm',
|
||||
),
|
||||
cancelButtonText: this.$t('devices.wireless.connect.error.cancel'),
|
||||
confirmButtonText: this.$t('device.wireless.connect.error.confirm'),
|
||||
cancelButtonText: this.$t('device.wireless.connect.error.cancel'),
|
||||
type: 'warning',
|
||||
},
|
||||
)
|
||||
@ -432,7 +430,7 @@ export default {
|
||||
try {
|
||||
await this.$adb.disconnect(host, port)
|
||||
await sleep()
|
||||
this.$message.success(this.$t('devices.wireless.disconnect.success'))
|
||||
this.$message.success(this.$t('device.wireless.disconnect.success'))
|
||||
}
|
||||
catch (error) {
|
||||
if (error.message)
|
||||
|
@ -3,7 +3,7 @@
|
||||
<div class="pb-4 pr-2 flex items-center justify-between">
|
||||
<div class="">
|
||||
<el-select
|
||||
v-model="scopeValue"
|
||||
v-model="deviceScope"
|
||||
value-key=""
|
||||
:placeholder="$t('preferences.scope.placeholder')"
|
||||
filterable
|
||||
@ -57,8 +57,8 @@
|
||||
</div>
|
||||
<div class="grid gap-6 pr-2">
|
||||
<el-card
|
||||
v-for="(item, index) of scrcpyModel"
|
||||
:key="index"
|
||||
v-for="(item, parentId) of preferenceModel"
|
||||
:key="parentId"
|
||||
shadow="hover"
|
||||
class=""
|
||||
>
|
||||
@ -68,7 +68,7 @@
|
||||
{{ item.label }}
|
||||
</div>
|
||||
<div class="flex-none pl-4">
|
||||
<el-button type="primary" text @click="handleReset(item.type)">
|
||||
<el-button type="primary" text @click="handleReset(parentId)">
|
||||
{{ $t("preferences.reset") }}
|
||||
</el-button>
|
||||
</div>
|
||||
@ -77,13 +77,13 @@
|
||||
<div class="">
|
||||
<el-form
|
||||
ref="elForm"
|
||||
:model="scrcpyForm"
|
||||
:model="preferenceData"
|
||||
label-width="170px"
|
||||
class="pr-8 pt-4"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col
|
||||
v-for="(item_1, index_1) of getSubModel(item.type)"
|
||||
v-for="(item_1, index_1) of getSubModel(item)"
|
||||
:key="index_1"
|
||||
:span="12"
|
||||
:offset="0"
|
||||
@ -111,28 +111,29 @@
|
||||
}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-input
|
||||
v-if="item_1.type === 'input'"
|
||||
v-if="item_1.type === 'Input'"
|
||||
v-bind="item_1.props || {}"
|
||||
v-model="scrcpyForm[item_1.field]"
|
||||
v-model="preferenceData[item_1.field]"
|
||||
class="!w-full"
|
||||
:title="item_1.placeholder"
|
||||
:placeholder="item_1.placeholder"
|
||||
clearable
|
||||
></el-input>
|
||||
<el-input
|
||||
v-if="item_1.type === 'input.number'"
|
||||
v-else-if="item_1.type === 'Input.number'"
|
||||
v-bind="item_1.props || {}"
|
||||
v-model.number="scrcpyForm[item_1.field]"
|
||||
v-model.number="preferenceData[item_1.field]"
|
||||
class="!w-full"
|
||||
:title="item_1.placeholder"
|
||||
:placeholder="item_1.placeholder"
|
||||
clearable
|
||||
></el-input>
|
||||
<el-input
|
||||
v-if="item_1.type === 'input.path'"
|
||||
v-else-if="item_1.type === 'Input.path'"
|
||||
v-bind="item_1.props || {}"
|
||||
v-model="scrcpyForm[item_1.field]"
|
||||
v-model="preferenceData[item_1.field]"
|
||||
class="!w-full"
|
||||
clearable
|
||||
:placeholder="item_1.placeholder"
|
||||
@ -151,18 +152,18 @@
|
||||
</template>
|
||||
</el-input>
|
||||
<el-switch
|
||||
v-if="item_1.type === 'switch'"
|
||||
v-else-if="item_1.type === 'Switch'"
|
||||
v-bind="item_1.props || {}"
|
||||
v-model="scrcpyForm[item_1.field]"
|
||||
v-model="preferenceData[item_1.field]"
|
||||
class="!w-full"
|
||||
clearable
|
||||
:title="item_1.placeholder"
|
||||
></el-switch>
|
||||
|
||||
<el-select
|
||||
v-if="item_1.type === 'select'"
|
||||
v-else-if="item_1.type === 'Select'"
|
||||
v-bind="item_1.props || {}"
|
||||
v-model="scrcpyForm[item_1.field]"
|
||||
v-model="preferenceData[item_1.field]"
|
||||
:placeholder="item_1.placeholder"
|
||||
class="!w-full"
|
||||
clearable
|
||||
@ -188,43 +189,20 @@
|
||||
|
||||
<script>
|
||||
import { debounce } from 'lodash-es'
|
||||
import { useScrcpyStore } from '@/store/index.js'
|
||||
import { usePreferenceStore } from '@/store/index.js'
|
||||
import LoadingIcon from '@/components/Device/ControlBar/LoadingIcon/index.vue'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
const scrcpyStore = useScrcpyStore()
|
||||
const preferenceStore = usePreferenceStore()
|
||||
|
||||
// console.raw('preferenceStore.data', preferenceStore.data)
|
||||
// console.raw('preferenceStore.model', preferenceStore.model)
|
||||
|
||||
return {
|
||||
scrcpyModel: [
|
||||
{
|
||||
label: this.$t('preferences.custom.name'),
|
||||
type: 'custom',
|
||||
},
|
||||
{
|
||||
label: this.$t('preferences.video.name'),
|
||||
type: 'video',
|
||||
},
|
||||
{
|
||||
label: this.$t('preferences.device.name'),
|
||||
type: 'device',
|
||||
},
|
||||
{
|
||||
label: this.$t('preferences.window.name'),
|
||||
type: 'window',
|
||||
},
|
||||
{
|
||||
label: this.$t('preferences.record.name'),
|
||||
type: 'record',
|
||||
},
|
||||
{
|
||||
label: this.$t('preferences.audio.name'),
|
||||
type: 'audio',
|
||||
},
|
||||
],
|
||||
scrcpyForm: { ...scrcpyStore.config },
|
||||
|
||||
scopeValue: scrcpyStore.scope,
|
||||
preferenceModel: preferenceStore.model,
|
||||
preferenceData: preferenceStore.data,
|
||||
deviceScope: preferenceStore.deviceScope,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -247,18 +225,23 @@ export default {
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
scrcpyForm: {
|
||||
preferenceData: {
|
||||
handler() {
|
||||
this.handleSave()
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
scopeValue: {
|
||||
handler(value) {
|
||||
deviceScope: {
|
||||
async handler(value) {
|
||||
if (value === 'global') {
|
||||
return
|
||||
this.$store.preference.resetModel()
|
||||
return false
|
||||
}
|
||||
this.getDisplay(value)
|
||||
|
||||
const display = await this.$adb.display(value)
|
||||
|
||||
this.$store.preference.setModelParams('video', { display })
|
||||
this.preferenceModel = this.$store.preference.model
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
@ -271,20 +254,13 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
handleResetAll() {
|
||||
this.$store.scrcpy.reset(this.scopeValue)
|
||||
this.scrcpyForm = this.$store.scrcpy.config
|
||||
this.$store.preference.reset(this.deviceScope)
|
||||
this.preferenceData = this.$store.preference.data
|
||||
},
|
||||
onScopeChange(value) {
|
||||
const replaceIPValue = this.$store.device.replaceIP(value)
|
||||
this.$store.scrcpy.setScope(replaceIPValue)
|
||||
this.scrcpyForm = this.$store.scrcpy.config
|
||||
},
|
||||
async getDisplay(value) {
|
||||
const display = await this.$adb.display(value)
|
||||
|
||||
console.log('display', display)
|
||||
|
||||
this.$store.scrcpy.setModel('video', { display })
|
||||
const replaceValue = this.$replaceIP(value)
|
||||
this.$store.preference.setScope(replaceValue)
|
||||
this.preferenceData = this.$store.preference.data
|
||||
},
|
||||
async handleImport() {
|
||||
try {
|
||||
@ -301,7 +277,7 @@ export default {
|
||||
|
||||
this.$message.success(this.$t('preferences.config.import.success'))
|
||||
|
||||
this.scrcpyForm = this.$store.scrcpy.init()
|
||||
this.preferenceData = this.$store.preference.init()
|
||||
}
|
||||
catch (error) {
|
||||
if (error.message) {
|
||||
@ -344,7 +320,7 @@ export default {
|
||||
},
|
||||
async handleSelect({ field }, { properties, filters } = {}) {
|
||||
try {
|
||||
const defaultPath = this.scrcpyForm[field]
|
||||
const defaultPath = this.preferenceData[field]
|
||||
const files = await this.$electron.ipcRenderer.invoke(
|
||||
'show-open-dialog',
|
||||
{
|
||||
@ -360,7 +336,7 @@ export default {
|
||||
|
||||
const value = files[0]
|
||||
|
||||
this.scrcpyForm[field] = value
|
||||
this.preferenceData[field] = value
|
||||
}
|
||||
catch (error) {
|
||||
if (error.message) {
|
||||
@ -370,20 +346,22 @@ export default {
|
||||
}
|
||||
},
|
||||
handleSave() {
|
||||
this.$store.scrcpy.setConfig(this.scrcpyForm)
|
||||
this.$store.preference.setData(this.preferenceData)
|
||||
this.$message.success(this.$t('preferences.config.save.placeholder'))
|
||||
},
|
||||
getSubModel(type) {
|
||||
console.log('getSubModel')
|
||||
const value = this.$store.scrcpy.getModel(type)
|
||||
return value
|
||||
getSubModel(item) {
|
||||
const data = item?.children() || []
|
||||
|
||||
console.raw(`getSubModel.${item.field}.data`, data)
|
||||
|
||||
return data
|
||||
},
|
||||
handleReset(type) {
|
||||
this.scrcpyForm = {
|
||||
...this.scrcpyForm,
|
||||
...this.$store.scrcpy.getDefaultConfig(type),
|
||||
this.preferenceData = {
|
||||
...this.preferenceData,
|
||||
...this.$store.preference.getDefaultData(type),
|
||||
}
|
||||
this.$store.scrcpy.setConfig(this.scrcpyForm)
|
||||
this.$store.preference.setData(this.preferenceData)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -1,294 +1 @@
|
||||
{
|
||||
"common": {
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm"
|
||||
},
|
||||
"devices": {
|
||||
"name": "Devices",
|
||||
"loading": "Devices loading...",
|
||||
"empty": "No device detected",
|
||||
"wireless": {
|
||||
"name": "Wireless",
|
||||
"mode": "Wireless mode",
|
||||
"connect": {
|
||||
"name": "Connect",
|
||||
"error": {
|
||||
"title": "连接设备失败",
|
||||
"detail": "错误详情",
|
||||
"reasons": [
|
||||
"可能有以下原因",
|
||||
"IP地址或端口号错误",
|
||||
"设备未与当前电脑配对成功",
|
||||
"电脑网络和提供的设备网络IP不在同一个局域网中",
|
||||
"adb 依赖路径错误",
|
||||
"其他未知错误"
|
||||
],
|
||||
"confirm": "无线配对",
|
||||
"cancel": "@:common.cancel",
|
||||
"no-address": "无线调试地址不能为空"
|
||||
},
|
||||
"success": "连接设备成功"
|
||||
},
|
||||
"disconnect": {
|
||||
"start": "断开连接",
|
||||
"progress": "正在断开",
|
||||
"success": "断开连接成功"
|
||||
}
|
||||
},
|
||||
"reset": {
|
||||
"title": "操作失败",
|
||||
"reasons": [
|
||||
"通常情况下,这可能是因为更新 Escrcpy 后,缓存的依赖配置不兼容所导致的,是否重置依赖配置?",
|
||||
"注意:重置后,之前保存的依赖配置将会被清除,因此建议在执行重置操作之前备份您的配置。"
|
||||
],
|
||||
"confirm": "重置依赖配置",
|
||||
"cancel": "@:common.cancel",
|
||||
"success": "操作成功,请重新尝试。"
|
||||
},
|
||||
"refresh": {
|
||||
"name": "Refresh"
|
||||
},
|
||||
"restart": {
|
||||
"name": "Restart"
|
||||
},
|
||||
"log": {
|
||||
"name": "Logs"
|
||||
},
|
||||
"device": {
|
||||
"id": "ID",
|
||||
"name": "Name",
|
||||
"remark": "Remark",
|
||||
"permission": {
|
||||
"error": "设备可能未授权成功,请重新插拔设备并点击允许USB调试"
|
||||
}
|
||||
},
|
||||
"mirror": {
|
||||
"start": "Mirror",
|
||||
"progress": "Mirroring"
|
||||
},
|
||||
"record": {
|
||||
"start": "Record",
|
||||
"progress": "Recording",
|
||||
"success": {
|
||||
"title": "录制成功",
|
||||
"message": "是否前往录制位置进行查看?"
|
||||
}
|
||||
},
|
||||
"operates": {
|
||||
"name": "Operations",
|
||||
"install": "Install APP",
|
||||
"capture": "Capture",
|
||||
"reboot": "Reboot",
|
||||
"power": "Power",
|
||||
"notification": "Notification",
|
||||
"return": "Back",
|
||||
"home": "Home",
|
||||
"switch": "Switch"
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"name": "Preferences",
|
||||
"reset": "Resets",
|
||||
"scope": {
|
||||
"global": "Global",
|
||||
"placeholder": "偏好设置的作用域范围",
|
||||
"no-data": "暂无数据",
|
||||
"details": [
|
||||
"对全局或者单个设备设置不同的偏好配置",
|
||||
"全局:将对所有设备生效。",
|
||||
"单个设备:继承于全局配置,并对单个设备进行独立设置,仅对此设备生效。"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"import": {
|
||||
"name": "导入配置",
|
||||
"placeholder": "请选择要导入的配置文件",
|
||||
"success": "导入成功"
|
||||
},
|
||||
"export": {
|
||||
"name": "导出配置",
|
||||
"message": "导出配置",
|
||||
"placeholder": "请选择要导出的位置",
|
||||
"success": "导出成功"
|
||||
},
|
||||
"edit": {
|
||||
"name": "编辑配置"
|
||||
},
|
||||
"reset": {
|
||||
"name": "重置配置"
|
||||
},
|
||||
"save": {
|
||||
"name": "保存配置",
|
||||
"placeholder": "保存配置成功,将在下一次控制设备时生效"
|
||||
}
|
||||
},
|
||||
"custom": {
|
||||
"name": "Custom",
|
||||
"file": {
|
||||
"name": "File Path",
|
||||
"placeholder": "Put on the user desktop by default",
|
||||
"tips": "Screenshots and recorded audio and video exist here"
|
||||
},
|
||||
"adb": {
|
||||
"name": "ADB Path",
|
||||
"placeholder": "Please set the ADB path",
|
||||
"tips": "The address of the ADB used to connect the device. Note that this option is not affected by the configuration of a single device"
|
||||
},
|
||||
"scrcpy": {
|
||||
"name": "Scrcpy Path",
|
||||
"placeholder": "Please set the SCRCPY path",
|
||||
"tips": "The address of the SCRCPY used to connect the device. Note that this option is not affected by the configuration of a single device"
|
||||
}
|
||||
},
|
||||
"video": {
|
||||
"name": "Video",
|
||||
"resolution": {
|
||||
"name": "Resolution",
|
||||
"placeholder": "Default device resolution",
|
||||
"tips": ""
|
||||
},
|
||||
"bit": {
|
||||
"name": "Bitrate",
|
||||
"placeholder": "Default 4M",
|
||||
"tips": ""
|
||||
},
|
||||
"refresh-rate": {
|
||||
"name": "Refresh Rate",
|
||||
"placeholder": "Default 60",
|
||||
"tips": ""
|
||||
},
|
||||
"decoder": {
|
||||
"name": "Decoder",
|
||||
"placeholder": "Default h264",
|
||||
"tips": ""
|
||||
},
|
||||
"encoder": {
|
||||
"name": "Encoder",
|
||||
"placeholder": "Default device encoder",
|
||||
"tips": ""
|
||||
},
|
||||
"screen-rotation": {
|
||||
"name": "Rotation",
|
||||
"placeholder": "Default device rotation",
|
||||
"tips": ""
|
||||
},
|
||||
"screen-cropping": {
|
||||
"name": "Cropping",
|
||||
"placeholder": "Default no cropping",
|
||||
"tips": ""
|
||||
},
|
||||
"multi-display": {
|
||||
"name": "Multi-Display",
|
||||
"placeholder": "Default 0 (main)",
|
||||
"tips": ""
|
||||
},
|
||||
"video-buffering": {
|
||||
"name": "Video Buffering",
|
||||
"placeholder": "Default 0ms",
|
||||
"tips": ""
|
||||
},
|
||||
"audio-buffering": {
|
||||
"name": "Audio Buffering",
|
||||
"placeholder": "Default 0ms",
|
||||
"tips": ""
|
||||
},
|
||||
"receiver-buffering": {
|
||||
"name": "Receiver Buffering",
|
||||
"placeholder": "Default 0ms",
|
||||
"tips": ""
|
||||
},
|
||||
"disable": {
|
||||
"name": "Disable Video",
|
||||
"placeholder": "Disable video if enabled",
|
||||
"tips": ""
|
||||
}
|
||||
},
|
||||
"device": {
|
||||
"name": "Device",
|
||||
"show-touch": {
|
||||
"name": "Show Touches",
|
||||
"placeholder": "Enable to show tap feedback in developer options",
|
||||
"tips": "Only on physical devices"
|
||||
},
|
||||
"stay-awake": {
|
||||
"name": "Stay Awake",
|
||||
"placeholder": "Enable to prevent sleep",
|
||||
"tips": "Wired connection only"
|
||||
},
|
||||
"control-in-close-screen": {
|
||||
"name": "Turn Off Screen",
|
||||
"placeholder": "Automatically turn off screen when controlling device",
|
||||
"tips": ""
|
||||
},
|
||||
"control-end-video": {
|
||||
"name": "Turn Off at End",
|
||||
"placeholder": "Automatically turn off screen when control stops",
|
||||
"tips": ""
|
||||
},
|
||||
"control-in-stop-charging": {
|
||||
"name": "Stop Charging",
|
||||
"placeholder": "Stop charging when controlling device",
|
||||
"tips": "May not work on some models"
|
||||
}
|
||||
},
|
||||
"window": {
|
||||
"name": "Window",
|
||||
"borderless": {
|
||||
"name": "Borderless",
|
||||
"placeholder": "Removes window border",
|
||||
"tips": ""
|
||||
},
|
||||
"full-screen": {
|
||||
"name": "Fullscreen",
|
||||
"placeholder": "Fullscreen mode",
|
||||
"tips": ""
|
||||
},
|
||||
"always-top": {
|
||||
"name": "Always on Top",
|
||||
"placeholder": "Window always on top",
|
||||
"tips": ""
|
||||
},
|
||||
"disable-screen-saver": {
|
||||
"name": "Disable Screen Saver",
|
||||
"placeholder": "Disables screen saver",
|
||||
"tips": ""
|
||||
}
|
||||
},
|
||||
"record": {
|
||||
"name": "Recording",
|
||||
"format": {
|
||||
"name": "Format",
|
||||
"placeholder": "Default .mp4 format",
|
||||
"tips": ""
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"name": "Audio",
|
||||
"disable": {
|
||||
"name": "Disable Audio",
|
||||
"placeholder": "Disables audio",
|
||||
"tips": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"name": "About",
|
||||
"description": "📱 Display and control your Android device with graphical Scrcpy, powered by Electron",
|
||||
"update": "Check for updates",
|
||||
"update-not-available": "Already up to date",
|
||||
"update-error": {
|
||||
"title": "Update check failed",
|
||||
"message": "You may need a VPN. Go to releases page to download manually?"
|
||||
},
|
||||
"update-downloaded": {
|
||||
"title": "New version downloaded",
|
||||
"message": "Restart now to update?",
|
||||
"confirm": "Update"
|
||||
},
|
||||
"update-available": {
|
||||
"title": "New version available",
|
||||
"confirm": "Update"
|
||||
},
|
||||
"updating": "Updating..."
|
||||
}
|
||||
}
|
||||
{}
|
||||
|
@ -1,296 +1,169 @@
|
||||
{
|
||||
"common": {
|
||||
"cancel": "取消",
|
||||
"confirm": "确认"
|
||||
},
|
||||
"devices": {
|
||||
"name": "设备列表",
|
||||
"loading": "努力加载中...",
|
||||
"empty": "没有检测到设备",
|
||||
|
||||
"wireless": {
|
||||
"name": "无线连接",
|
||||
"mode": "无线模式",
|
||||
"connect": {
|
||||
"name": "连接设备",
|
||||
"error": {
|
||||
"title": "连接设备失败",
|
||||
"detail": "错误详情",
|
||||
"reasons": [
|
||||
"可能有以下原因",
|
||||
"IP地址或端口号错误",
|
||||
"设备未与当前电脑配对成功",
|
||||
"电脑网络和提供的设备网络IP不在同一个局域网中",
|
||||
"adb 依赖路径错误",
|
||||
"其他未知错误"
|
||||
],
|
||||
"confirm": "无线配对",
|
||||
"cancel": "@:common.cancel",
|
||||
"no-address": "无线调试地址不能为空"
|
||||
},
|
||||
"success": "连接设备成功"
|
||||
},
|
||||
"disconnect": {
|
||||
"start": "断开连接",
|
||||
"progress": "正在断开",
|
||||
"success": "断开连接成功"
|
||||
}
|
||||
},
|
||||
"reset": {
|
||||
"title": "操作失败",
|
||||
"reasons": [
|
||||
"通常情况下,这可能是因为更新 Escrcpy 后,缓存的依赖配置不兼容所导致的,是否重置依赖配置?",
|
||||
"注意:重置后,之前保存的依赖配置将会被清除,因此建议在执行重置操作之前备份您的配置。"
|
||||
],
|
||||
"confirm": "重置依赖配置",
|
||||
"cancel": "@:common.cancel",
|
||||
"success": "操作成功,请重新尝试。"
|
||||
},
|
||||
"refresh": {
|
||||
"name": "刷新设备"
|
||||
},
|
||||
"restart": {
|
||||
"name": "重启服务"
|
||||
},
|
||||
"log": {
|
||||
"name": "运行日志"
|
||||
},
|
||||
"device": {
|
||||
"id": "设备 ID",
|
||||
"name": "设备名称",
|
||||
"remark": "备注",
|
||||
"permission": {
|
||||
"error": "设备可能未授权成功,请重新插拔设备并点击允许USB调试"
|
||||
}
|
||||
},
|
||||
"mirror": {
|
||||
"start": "开始镜像",
|
||||
"progress": "正在镜像"
|
||||
},
|
||||
"record": {
|
||||
"start": "开始录制",
|
||||
"progress": "正在录制",
|
||||
"success": {
|
||||
"title": "录制成功",
|
||||
"message": "是否前往录制位置进行查看?"
|
||||
}
|
||||
},
|
||||
"operates": {
|
||||
"name": "操作",
|
||||
"more": "设备交互",
|
||||
"install": "安装应用",
|
||||
"capture": "截取屏幕",
|
||||
"reboot": "重启设备",
|
||||
"power": "电源键",
|
||||
"notification": "通知栏",
|
||||
"return": "切换键",
|
||||
"home": "切换键",
|
||||
"switch": "切换键"
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"name": "偏好设置",
|
||||
"reset": "恢复默认值",
|
||||
"scope": {
|
||||
"global": "全局",
|
||||
"placeholder": "偏好设置的作用域范围",
|
||||
"no-data": "暂无数据",
|
||||
"details": [
|
||||
"对全局或者单个设备设置不同的偏好配置",
|
||||
"全局:将对所有设备生效。",
|
||||
"单个设备:继承于全局配置,并对单个设备进行独立设置,仅对此设备生效。"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"import": {
|
||||
"name": "导入",
|
||||
"placeholder": "请选择要导入的配置文件",
|
||||
"success": "导入成功"
|
||||
},
|
||||
"export": {
|
||||
"name": "导出",
|
||||
"message": "导出配置",
|
||||
"placeholder": "请选择要导出的位置",
|
||||
"success": "导出成功"
|
||||
},
|
||||
"edit": {
|
||||
"name": "编辑"
|
||||
},
|
||||
"reset": {
|
||||
"name": "重置"
|
||||
},
|
||||
"save": {
|
||||
"name": "保存配置",
|
||||
"placeholder": "保存配置成功,将在下一次控制设备时生效"
|
||||
}
|
||||
},
|
||||
"custom": {
|
||||
"name": "自定义",
|
||||
"file": {
|
||||
"name": "文件存储路径",
|
||||
"placeholder": "默认情况下放在用户桌面上",
|
||||
"tips": "截图和录制的音视频存放在这里"
|
||||
},
|
||||
"adb": {
|
||||
"name": "adb 路径",
|
||||
"placeholder": "请设置 adb 路径",
|
||||
"tips": "用于连接设备的 adb 地址。注意:此选项不受单个设备配置的影响"
|
||||
},
|
||||
"scrcpy": {
|
||||
"name": "scrcpy 路径",
|
||||
"placeholder": "请设置 scrcpy 路径",
|
||||
"tips": "用于连接设备的 scrcpy 地址。注意:此选项不受单个设备配置的影响"
|
||||
}
|
||||
},
|
||||
"video": {
|
||||
"name": "视频控制",
|
||||
"resolution": {
|
||||
"name": "分辨率",
|
||||
"placeholder": "默认值为设备分辨率,如 1920",
|
||||
"tips": ""
|
||||
},
|
||||
"bit": {
|
||||
"name": "比特率",
|
||||
"placeholder": "默认值为 4M,等同于 4000000",
|
||||
"tips": ""
|
||||
},
|
||||
"refresh-rate": {
|
||||
"name": "刷新率",
|
||||
"placeholder": "默认值为 60",
|
||||
"tips": ""
|
||||
},
|
||||
"decoder": {
|
||||
"name": "视频解码器",
|
||||
"placeholder": "默认值为 h264",
|
||||
"tips": ""
|
||||
},
|
||||
"encoder": {
|
||||
"name": "视频编码器",
|
||||
"placeholder": "默认值为设备默认编码器",
|
||||
"tips": ""
|
||||
},
|
||||
"screen-rotation": {
|
||||
"name": "屏幕旋转",
|
||||
"placeholder": "默认值为设备屏幕旋转角度",
|
||||
"tips": ""
|
||||
},
|
||||
"screen-cropping": {
|
||||
"name": "屏幕裁剪",
|
||||
"placeholder": "默认不裁剪,格式为 1224:1440:0:0",
|
||||
"tips": ""
|
||||
},
|
||||
"multi-display": {
|
||||
"name": "多显示器",
|
||||
"placeholder": "默认值为 0(主屏幕)",
|
||||
"tips": ""
|
||||
},
|
||||
"video-buffering": {
|
||||
"name": "视频缓冲",
|
||||
"placeholder": "默认值为 0ms",
|
||||
"tips": ""
|
||||
},
|
||||
"audio-buffering": {
|
||||
"name": "音频缓冲",
|
||||
"placeholder": "默认值为 0ms",
|
||||
"tips": ""
|
||||
},
|
||||
"receiver-buffering": {
|
||||
"name": "接收器缓冲(v412)",
|
||||
"placeholder": "默认值为 0ms",
|
||||
"tips": ""
|
||||
},
|
||||
"disable": {
|
||||
"name": "禁用视频",
|
||||
"placeholder": "开启后将禁用视频",
|
||||
"tips": ""
|
||||
}
|
||||
},
|
||||
"device": {
|
||||
"name": "设备控制",
|
||||
"show-touch": {
|
||||
"name": "展示触摸点",
|
||||
"placeholder": "开启后将打开开发者选项中的显示点按触摸反馈",
|
||||
"tips": "仅在物理设备上展示"
|
||||
},
|
||||
"stay-awake": {
|
||||
"name": "保持清醒",
|
||||
"placeholder": "开启以防止设备进入睡眠状态",
|
||||
"tips": "仅有线方式连接时有效"
|
||||
},
|
||||
"control-in-close-screen": {
|
||||
"name": "控制时关闭屏幕",
|
||||
"placeholder": "开启后控制设备时将自动关闭设备屏幕",
|
||||
"tips": ""
|
||||
},
|
||||
"control-end-video": {
|
||||
"name": "控制结束关闭屏幕",
|
||||
"placeholder": "开启后停止控制设备将自动关闭设备屏幕",
|
||||
"tips": ""
|
||||
},
|
||||
"control-in-stop-charging": {
|
||||
"name": "控制时停止充电",
|
||||
"placeholder": "开启后控制设备时将停止充电",
|
||||
"tips": "某些机型上似乎不起作用"
|
||||
}
|
||||
},
|
||||
"window": {
|
||||
"name": "窗口控制",
|
||||
"borderless": {
|
||||
"name": "无边框模式",
|
||||
"placeholder": "开启后控制窗口将变为无边框模式",
|
||||
"tips": ""
|
||||
},
|
||||
"full-screen": {
|
||||
"name": "全屏模式",
|
||||
"placeholder": "开启后控制窗口将全屏显示模式",
|
||||
"tips": ""
|
||||
},
|
||||
"always-top": {
|
||||
"name": "始终位于顶部",
|
||||
"placeholder": "开启后控制窗口将始终位于顶部",
|
||||
"tips": ""
|
||||
},
|
||||
"disable-screen-saver": {
|
||||
"name": "禁用屏幕保护程序",
|
||||
"placeholder": "开启后将禁用计算机屏幕保护程序",
|
||||
"tips": ""
|
||||
}
|
||||
},
|
||||
"record": {
|
||||
"name": "音视频录制",
|
||||
"format": {
|
||||
"name": "录制视频格式",
|
||||
"placeholder": "默认为 *.mp4 格式",
|
||||
"tips": ""
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"name": "音频控制",
|
||||
"disable": {
|
||||
"name": "禁用音频",
|
||||
"placeholder": "开启后将禁用音频功能",
|
||||
"tips": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"name": "关于",
|
||||
"description": "📱 使用图形化的 Scrcpy 显示和控制您的 Android 设备,由 Electron 驱动",
|
||||
"update": "检查并更新",
|
||||
"update-not-available": "已经是最新版本",
|
||||
"update-error": {
|
||||
"title": "检查更新失败",
|
||||
"message": "你可能需要科学上网,是否前往发布页面手动下载更新?"
|
||||
},
|
||||
"update-downloaded": {
|
||||
"title": "下载新版本成功",
|
||||
"message": "是否立即重启更新?",
|
||||
"confirm": "更新"
|
||||
},
|
||||
"update-available": {
|
||||
"title": "发现新版本",
|
||||
"confirm": "更新"
|
||||
},
|
||||
"updating": "正在更新中"
|
||||
}
|
||||
"common.cancel": "取消",
|
||||
"common.confirm": "确认",
|
||||
"device.list": "设备列表",
|
||||
"device.list.loading": "努力加载中...",
|
||||
"device.list.empty": "没有检测到设备",
|
||||
"device.id": "设备 ID",
|
||||
"device.name": "设备名称",
|
||||
"device.remark": "备注",
|
||||
"device.permission.error": "设备可能未授权成功,请重新插拔设备并点击允许USB调试",
|
||||
"device.wireless.name": "无线连接",
|
||||
"device.wireless.mode": "无线模式",
|
||||
"device.wireless.connect.name": "连接设备",
|
||||
"device.wireless.connect.error.title": "连接设备失败",
|
||||
"device.wireless.connect.error.detail": "错误详情",
|
||||
"device.wireless.connect.error.reasons[0]": "可能有以下原因",
|
||||
"device.wireless.connect.error.reasons[1]": "IP地址或端口号错误",
|
||||
"device.wireless.connect.error.reasons[2]": "设备未与当前电脑配对成功",
|
||||
"device.wireless.connect.error.reasons[3]": "电脑网络和提供的设备网络IP不在同一个局域网中",
|
||||
"device.wireless.connect.error.reasons[4]": "adb 依赖路径错误",
|
||||
"device.wireless.connect.error.reasons[5]": "其他未知错误",
|
||||
"device.wireless.connect.error.confirm": "无线配对",
|
||||
"device.wireless.connect.error.cancel": "@:common.cancel",
|
||||
"device.wireless.connect.error.no-address": "无线调试地址不能为空",
|
||||
"device.wireless.connect.success": "连接设备成功",
|
||||
"device.wireless.disconnect.start": "断开连接",
|
||||
"device.wireless.disconnect.progress": "正在断开",
|
||||
"device.wireless.disconnect.success": "断开连接成功",
|
||||
"device.reset.title": "操作失败",
|
||||
"device.reset.reasons[0]": "通常情况下,这可能是因为更新 Escrcpy 后,缓存的依赖配置不兼容所导致的,是否重置依赖配置?",
|
||||
"device.reset.reasons[1]": "注意:重置后,之前保存的依赖配置将会被清除,因此建议在执行重置操作之前备份您的配置。",
|
||||
"device.reset.confirm": "重置依赖配置",
|
||||
"device.reset.cancel": "@:common.cancel",
|
||||
"device.reset.success": "操作成功,请重新尝试。",
|
||||
"device.refresh.name": "刷新设备",
|
||||
"device.restart.name": "重启服务",
|
||||
"device.log.name": "运行日志",
|
||||
"device.mirror.start": "开始镜像",
|
||||
"device.mirror.progress": "正在镜像",
|
||||
"device.record.start": "开始录制",
|
||||
"device.record.progress": "正在录制",
|
||||
"device.record.success.title": "录制成功",
|
||||
"device.record.success.message": "是否前往录制位置进行查看?",
|
||||
"device.operates.name": "操作",
|
||||
"device.operates.more": "设备交互",
|
||||
"device.operates.install": "安装应用",
|
||||
"device.operates.capture": "截取屏幕",
|
||||
"device.operates.reboot": "重启设备",
|
||||
"device.operates.power": "电源键",
|
||||
"device.operates.notification": "通知栏",
|
||||
"device.operates.return": "切换键",
|
||||
"device.operates.home": "切换键",
|
||||
"device.operates.switch": "切换键",
|
||||
"preferences.name": "偏好设置",
|
||||
"preferences.reset": "恢复默认值",
|
||||
"preferences.scope.global": "全局",
|
||||
"preferences.scope.placeholder": "偏好设置的作用域范围",
|
||||
"preferences.scope.no-data": "暂无数据",
|
||||
"preferences.scope.details[0]": "对全局或者单个设备设置不同的偏好配置",
|
||||
"preferences.scope.details[1]": "全局:将对所有设备生效。",
|
||||
"preferences.scope.details[2]": "单个设备:继承于全局配置,并对单个设备进行独立设置,仅对此设备生效。",
|
||||
"preferences.config.import.name": "导入",
|
||||
"preferences.config.import.placeholder": "请选择要导入的配置文件",
|
||||
"preferences.config.import.success": "导入成功",
|
||||
"preferences.config.export.name": "导出",
|
||||
"preferences.config.export.message": "导出配置",
|
||||
"preferences.config.export.placeholder": "请选择要导出的位置",
|
||||
"preferences.config.export.success": "导出成功",
|
||||
"preferences.config.edit.name": "编辑",
|
||||
"preferences.config.reset.name": "重置",
|
||||
"preferences.config.save.name": "保存配置",
|
||||
"preferences.config.save.placeholder": "保存配置成功,将在下一次控制设备时生效",
|
||||
"preferences.common.name": "通用",
|
||||
"preferences.common.file.name": "文件存储路径",
|
||||
"preferences.common.file.placeholder": "默认情况下放在用户桌面上",
|
||||
"preferences.common.file.tips": "截图和录制的音视频存放在这里",
|
||||
"preferences.common.adb.name": "adb 路径",
|
||||
"preferences.common.adb.placeholder": "请设置 adb 路径",
|
||||
"preferences.common.adb.tips": "用于连接设备的 adb 地址。注意:此选项不受单个设备配置的影响",
|
||||
"preferences.common.scrcpy.name": "scrcpy 路径",
|
||||
"preferences.common.scrcpy.placeholder": "请设置 scrcpy 路径",
|
||||
"preferences.common.scrcpy.tips": "用于连接设备的 scrcpy 地址。注意:此选项不受单个设备配置的影响",
|
||||
"preferences.video.name": "视频控制",
|
||||
"preferences.video.resolution.name": "分辨率",
|
||||
"preferences.video.resolution.placeholder": "默认值为设备分辨率,如 1920",
|
||||
"preferences.video.resolution.tips": "",
|
||||
"preferences.video.bit.name": "比特率",
|
||||
"preferences.video.bit.placeholder": "默认值为 4M,等同于 4000000",
|
||||
"preferences.video.bit.tips": "",
|
||||
"preferences.video.refresh-rate.name": "刷新率",
|
||||
"preferences.video.refresh-rate.placeholder": "默认值为 60",
|
||||
"preferences.video.refresh-rate.tips": "",
|
||||
"preferences.video.decoder.name": "视频解码器",
|
||||
"preferences.video.decoder.placeholder": "默认值为 h264",
|
||||
"preferences.video.decoder.tips": "",
|
||||
"preferences.video.encoder.name": "视频编码器",
|
||||
"preferences.video.encoder.placeholder": "默认值为设备默认编码器",
|
||||
"preferences.video.encoder.tips": "",
|
||||
"preferences.video.screen-rotation.name": "屏幕旋转",
|
||||
"preferences.video.screen-rotation.placeholder": "默认值为设备屏幕旋转角度",
|
||||
"preferences.video.screen-rotation.tips": "",
|
||||
"preferences.video.screen-cropping.name": "屏幕裁剪",
|
||||
"preferences.video.screen-cropping.placeholder": "默认不裁剪,格式为 1224:1440:0:0",
|
||||
"preferences.video.screen-cropping.tips": "",
|
||||
"preferences.video.multi-display.name": "多显示器",
|
||||
"preferences.video.multi-display.placeholder": "默认值为 0(主屏幕)",
|
||||
"preferences.video.multi-display.tips": "",
|
||||
"preferences.video.video-buffering.name": "视频缓冲",
|
||||
"preferences.video.video-buffering.placeholder": "默认值为 0ms",
|
||||
"preferences.video.video-buffering.tips": "",
|
||||
"preferences.video.audio-buffering.name": "音频缓冲",
|
||||
"preferences.video.audio-buffering.placeholder": "默认值为 0ms",
|
||||
"preferences.video.audio-buffering.tips": "",
|
||||
"preferences.video.receiver-buffering.name": "接收器缓冲(v412)",
|
||||
"preferences.video.receiver-buffering.placeholder": "默认值为 0ms",
|
||||
"preferences.video.receiver-buffering.tips": "",
|
||||
"preferences.video.disable.name": "禁用视频",
|
||||
"preferences.video.disable.placeholder": "开启后将禁用视频",
|
||||
"preferences.video.disable.tips": "",
|
||||
"preferences.device.name": "设备控制",
|
||||
"preferences.device.show-touch.name": "展示触摸点",
|
||||
"preferences.device.show-touch.placeholder": "开启后将打开开发者选项中的显示点按触摸反馈",
|
||||
"preferences.device.show-touch.tips": "仅在物理设备上展示",
|
||||
"preferences.device.stay-awake.name": "保持清醒",
|
||||
"preferences.device.stay-awake.placeholder": "开启以防止设备进入睡眠状态",
|
||||
"preferences.device.stay-awake.tips": "仅有线方式连接时有效",
|
||||
"preferences.device.control-in-close-screen.name": "控制时关闭屏幕",
|
||||
"preferences.device.control-in-close-screen.placeholder": "开启后控制设备时将自动关闭设备屏幕",
|
||||
"preferences.device.control-in-close-screen.tips": "",
|
||||
"preferences.device.control-end-video.name": "控制结束关闭屏幕",
|
||||
"preferences.device.control-end-video.placeholder": "开启后停止控制设备将自动关闭设备屏幕",
|
||||
"preferences.device.control-end-video.tips": "",
|
||||
"preferences.device.control-in-stop-charging.name": "控制时停止充电",
|
||||
"preferences.device.control-in-stop-charging.placeholder": "开启后控制设备时将停止充电",
|
||||
"preferences.device.control-in-stop-charging.tips": "某些机型上似乎不起作用",
|
||||
"preferences.window.name": "窗口控制",
|
||||
"preferences.window.borderless.name": "无边框模式",
|
||||
"preferences.window.borderless.placeholder": "开启后控制窗口将变为无边框模式",
|
||||
"preferences.window.borderless.tips": "",
|
||||
"preferences.window.full-screen.name": "全屏模式",
|
||||
"preferences.window.full-screen.placeholder": "开启后控制窗口将全屏显示模式",
|
||||
"preferences.window.full-screen.tips": "",
|
||||
"preferences.window.always-top.name": "始终位于顶部",
|
||||
"preferences.window.always-top.placeholder": "开启后控制窗口将始终位于顶部",
|
||||
"preferences.window.always-top.tips": "",
|
||||
"preferences.window.disable-screen-saver.name": "禁用屏幕保护程序",
|
||||
"preferences.window.disable-screen-saver.placeholder": "开启后将禁用计算机屏幕保护程序",
|
||||
"preferences.window.disable-screen-saver.tips": "",
|
||||
"preferences.record.name": "音视频录制",
|
||||
"preferences.record.format.name": "录制视频格式",
|
||||
"preferences.record.format.placeholder": "默认为 *.mp4 格式",
|
||||
"preferences.record.format.tips": "",
|
||||
"preferences.audio.name": "音频控制",
|
||||
"preferences.audio.disable.name": "禁用音频",
|
||||
"preferences.audio.disable.placeholder": "开启后将禁用音频功能",
|
||||
"preferences.audio.disable.tips": "",
|
||||
"about.name": "关于",
|
||||
"about.description": "📱 使用图形化的 Scrcpy 显示和控制您的 Android 设备,由 Electron 驱动",
|
||||
"about.update": "检查并更新",
|
||||
"about.update-not-available": "已经是最新版本",
|
||||
"about.update-error.title": "检查更新失败",
|
||||
"about.update-error.message": "你可能需要科学上网,是否前往发布页面手动下载更新?",
|
||||
"about.update-downloaded.title": "下载新版本成功",
|
||||
"about.update-downloaded.message": "是否立即重启更新?",
|
||||
"about.update-downloaded.confirm": "更新",
|
||||
"about.update-available.title": "发现新版本",
|
||||
"about.update-available.confirm": "更新",
|
||||
"about.update.progress": "正在更新中"
|
||||
}
|
||||
|
@ -1,17 +1,20 @@
|
||||
import { createPinia } from 'pinia'
|
||||
import { useScrcpyStore } from './scrcpy/index.js'
|
||||
import { useDeviceStore } from './device/index.js'
|
||||
import { usePreferenceStore } from './preference/index.js'
|
||||
|
||||
export { useScrcpyStore, useDeviceStore }
|
||||
export { useScrcpyStore, useDeviceStore, usePreferenceStore }
|
||||
|
||||
export default {
|
||||
install(app) {
|
||||
const store = createPinia()
|
||||
|
||||
app.use(store)
|
||||
|
||||
app.config.globalProperties.$store = {
|
||||
scrcpy: useScrcpyStore(),
|
||||
device: useDeviceStore(),
|
||||
preference: usePreferenceStore(),
|
||||
}
|
||||
},
|
||||
}
|
||||
|
129
src/store/preference/helpers/index.js
Normal file
129
src/store/preference/helpers/index.js
Normal file
@ -0,0 +1,129 @@
|
||||
import { cloneDeep, keyBy, mergeWith, uniq } from 'lodash-es'
|
||||
import model from '../model/index.js'
|
||||
|
||||
export function getModelFields(data = model) {
|
||||
return uniq(Object.values(data).map(item => item.field))
|
||||
}
|
||||
|
||||
const modelFields = getModelFields()
|
||||
|
||||
export function getModelMap(data = model) {
|
||||
const value = Object.entries(data).reduce((obj, [key, item]) => {
|
||||
const children
|
||||
= item?.children()?.map(item_1 => ({
|
||||
...item_1,
|
||||
parentField: item.field,
|
||||
parentId: key,
|
||||
})) || []
|
||||
|
||||
const subData = keyBy(children, 'field')
|
||||
|
||||
obj = {
|
||||
...obj,
|
||||
...subData,
|
||||
}
|
||||
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
// console.raw('getModelMap.value', value)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
export function getDefaultData(parentId) {
|
||||
const modelMap = getModelMap()
|
||||
|
||||
const value = Object.entries(modelMap).reduce((obj, [key, data]) => {
|
||||
if (!parentId || data.parentId === parentId) {
|
||||
obj[key] = data.value
|
||||
}
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
// console.raw('getDefaultData.value', value)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
export const getStoreData = (scope) => {
|
||||
const value = {}
|
||||
|
||||
modelFields.forEach((key) => {
|
||||
const storeValue = window.appStore.get(key) || {}
|
||||
if (key === 'scrcpy') {
|
||||
Object.assign(value, storeValue[scope || 'global'])
|
||||
return
|
||||
}
|
||||
|
||||
Object.assign(value, storeValue)
|
||||
})
|
||||
|
||||
// console.raw('getStoreData.value', value)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
export function setStoreData(data, scope) {
|
||||
const modelMap = getModelMap()
|
||||
|
||||
const fieldModel = modelFields.reduce((obj, key) => {
|
||||
obj[key] = {}
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
Object.entries(data).forEach(([key, value]) => {
|
||||
const { parentField } = modelMap[key]
|
||||
|
||||
fieldModel[parentField][key] = value
|
||||
})
|
||||
|
||||
const fieldList = Object.entries(fieldModel).reduce((arr, [field, value]) => {
|
||||
arr.push({
|
||||
field: field === 'scrcpy' ? `scrcpy.${scope}` : field,
|
||||
value,
|
||||
})
|
||||
return arr
|
||||
}, [])
|
||||
|
||||
// console.raw('setStoreData.fieldList', fieldList)
|
||||
|
||||
fieldList.forEach((item) => {
|
||||
window.appStore.set(item.field, item.value)
|
||||
})
|
||||
}
|
||||
|
||||
export function mergeConfig(object, sources, { debug = false } = {}) {
|
||||
const cloneObject = cloneDeep(object)
|
||||
const cloneSources = cloneDeep(sources)
|
||||
|
||||
const customizer = (objValue, srcValue, key) => {
|
||||
let value = srcValue || objValue
|
||||
|
||||
if (typeof srcValue === 'boolean') {
|
||||
value = srcValue
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
console.raw(key, value)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
const value = mergeWith(cloneObject, cloneSources, customizer)
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
export const getOtherFields = (excludeKey = '') => {
|
||||
const modelMap = getModelMap()
|
||||
const value = Object.entries(modelMap).reduce((arr, [key, data]) => {
|
||||
if (data.parentField !== excludeKey) {
|
||||
arr.push(data.field)
|
||||
}
|
||||
return arr
|
||||
}, [])
|
||||
|
||||
return value
|
||||
}
|
179
src/store/preference/index.js
Normal file
179
src/store/preference/index.js
Normal file
@ -0,0 +1,179 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import model from './model/index.js'
|
||||
|
||||
import {
|
||||
getDefaultData,
|
||||
getModelFields,
|
||||
getOtherFields,
|
||||
getStoreData,
|
||||
mergeConfig,
|
||||
setStoreData,
|
||||
} from './helpers/index.js'
|
||||
|
||||
import { replaceIP } from '@/utils/index.js'
|
||||
|
||||
const { adbPath, scrcpyPath } = window.electron?.configs || {}
|
||||
|
||||
export const usePreferenceStore = defineStore({
|
||||
id: 'app-preference',
|
||||
state() {
|
||||
return {
|
||||
model: cloneDeep(model),
|
||||
data: { ...getDefaultData() },
|
||||
deviceScope: window.appStore.get('scrcpy.deviceScope') || 'global',
|
||||
|
||||
scrcpyExcludeKeys: ['--record-format', ...getOtherFields('scrcpy')],
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
modelList() {
|
||||
return Object.values(this.model)
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
getDefaultData,
|
||||
init(scope = this.deviceScope) {
|
||||
const data = mergeConfig(getDefaultData(), getStoreData(scope))
|
||||
|
||||
this.data = data
|
||||
|
||||
return this.data
|
||||
},
|
||||
setScope(value) {
|
||||
this.deviceScope = replaceIP(value)
|
||||
window.appStore.set('scrcpy.deviceScope', this.deviceScope)
|
||||
this.init()
|
||||
},
|
||||
setData(data, scope = this.deviceScope) {
|
||||
const cloneData = cloneDeep(data)
|
||||
|
||||
// console.log('adbPath', adbPath)
|
||||
// console.log('scrcpyPath', scrcpyPath)
|
||||
|
||||
if (data.adbPath === adbPath) {
|
||||
delete cloneData.adbPath
|
||||
}
|
||||
|
||||
if (data.scrcpyPath === scrcpyPath) {
|
||||
delete cloneData.scrcpyPath
|
||||
}
|
||||
|
||||
setStoreData(cloneData, scope)
|
||||
|
||||
this.init(scope)
|
||||
},
|
||||
reset(scope) {
|
||||
if (!scope) {
|
||||
window.appStore.reset()
|
||||
}
|
||||
else {
|
||||
const fields = getModelFields()
|
||||
|
||||
fields.forEach((key) => {
|
||||
if (key === 'scrcpy') {
|
||||
this.deviceScope = scope
|
||||
window.appStore.set(`scrcpy.${replaceIP(scope)}`, {})
|
||||
return false
|
||||
}
|
||||
window.appStore.set(key, {})
|
||||
})
|
||||
}
|
||||
|
||||
this.init()
|
||||
},
|
||||
resetDeps(type) {
|
||||
switch (type) {
|
||||
case 'adb':
|
||||
window.appStore.set('common.adbPath', '')
|
||||
break
|
||||
case 'scrcpy':
|
||||
window.appStore.set('common.scrcpyPath', '')
|
||||
break
|
||||
default:
|
||||
window.appStore.set('common.adbPath', '')
|
||||
window.appStore.set('common.scrcpyPath', '')
|
||||
break
|
||||
}
|
||||
this.init()
|
||||
},
|
||||
getData(scope = this.scope) {
|
||||
const value = this.init(scope)
|
||||
return value
|
||||
},
|
||||
getScrcpyData(scope = this.scope) {
|
||||
const data = this.getData(scope)
|
||||
|
||||
if (!data) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const value = Object.entries(data)
|
||||
.reduce((arr, [key, value]) => {
|
||||
if (!value) {
|
||||
return arr
|
||||
}
|
||||
|
||||
if (this.scrcpyExcludeKeys.includes(key)) {
|
||||
return arr
|
||||
}
|
||||
|
||||
if (typeof value === 'boolean') {
|
||||
arr.push(key)
|
||||
}
|
||||
else {
|
||||
arr.push(`${key}=${value}`)
|
||||
}
|
||||
|
||||
return arr
|
||||
}, [])
|
||||
.join(' ')
|
||||
|
||||
console.log('getScrcpyData.value', value)
|
||||
|
||||
return value
|
||||
},
|
||||
getModel(key, params) {
|
||||
const handler = this.model[key]
|
||||
const value = handler(params)
|
||||
// console.log('setModel.value', value)
|
||||
|
||||
return value
|
||||
},
|
||||
setModelParams(key, ...args) {
|
||||
const handler = this.model[key]?.children
|
||||
|
||||
if (!handler) {
|
||||
return false
|
||||
}
|
||||
|
||||
const value = handler(...args)
|
||||
|
||||
console.raw('setModelParams.value', value)
|
||||
|
||||
this.model[key].children = () => value
|
||||
|
||||
return this.model
|
||||
},
|
||||
resetModel(key) {
|
||||
const keys = []
|
||||
if (key) {
|
||||
keys.push(key)
|
||||
}
|
||||
else {
|
||||
keys.push(...Object.keys(model))
|
||||
}
|
||||
|
||||
keys.forEach((value) => {
|
||||
if (!this.model?.[value]?.children) {
|
||||
return false
|
||||
}
|
||||
|
||||
this.model[value].children = (...args) =>
|
||||
model[value].children(...args)
|
||||
})
|
||||
|
||||
return true
|
||||
},
|
||||
},
|
||||
})
|
22
src/store/preference/model/audio/index.js
Normal file
22
src/store/preference/model/audio/index.js
Normal file
@ -0,0 +1,22 @@
|
||||
import { t } from '@/locales/index.js'
|
||||
|
||||
export default {
|
||||
label: t('preferences.audio.name'),
|
||||
field: 'scrcpy',
|
||||
|
||||
children: () => {
|
||||
// "[server] INFO: List of audio encoders:"
|
||||
// "--audio-codec=opus --audio-encoder='c2.android.opus.encoder'"
|
||||
// "--audio-codec=aac --audio-encoder='c2.android.aac.encoder'"
|
||||
// "--audio-codec=aac --audio-encoder='OMX.google.aac.encoder'"
|
||||
return [
|
||||
{
|
||||
label: t('preferences.audio.disable.name'),
|
||||
field: '--no-audio',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t('preferences.audio.disable.placeholder'),
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
47
src/store/preference/model/common/index.js
Normal file
47
src/store/preference/model/common/index.js
Normal file
@ -0,0 +1,47 @@
|
||||
import { t } from '@/locales/index.js'
|
||||
|
||||
export default {
|
||||
label: t('preferences.common.name'),
|
||||
field: 'common',
|
||||
|
||||
children: () => {
|
||||
const { adbPath, scrcpyPath, desktopPath }
|
||||
= window?.electron?.configs || {}
|
||||
|
||||
return [
|
||||
{
|
||||
label: t('preferences.common.file.name'),
|
||||
field: 'savePath',
|
||||
type: 'Input.path',
|
||||
value: desktopPath,
|
||||
placeholder: t('preferences.common.file.placeholder'),
|
||||
tips: t('preferences.common.file.tips'),
|
||||
properties: ['openDirectory'],
|
||||
},
|
||||
{
|
||||
label: t('preferences.common.adb.name'),
|
||||
field: 'adbPath',
|
||||
value: adbPath,
|
||||
type: 'Input.path',
|
||||
placeholder: t('preferences.common.adb.placeholder'),
|
||||
tips: t('preferences.common.adb.tips'),
|
||||
properties: ['openFile'],
|
||||
filters: [
|
||||
{ name: t('preferences.common.adb.name'), extensions: ['*'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t('preferences.common.scrcpy.name'),
|
||||
field: 'scrcpyPath',
|
||||
value: scrcpyPath,
|
||||
type: 'Input.path',
|
||||
placeholder: t('preferences.common.scrcpy.placeholder'),
|
||||
tips: t('preferences.common.scrcpy.tips'),
|
||||
properties: ['openFile'],
|
||||
filters: [
|
||||
{ name: t('preferences.common.scrcpy.name'), extensions: ['*'] },
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
52
src/store/preference/model/device/index.js
Normal file
52
src/store/preference/model/device/index.js
Normal file
@ -0,0 +1,52 @@
|
||||
import { t } from '@/locales/index.js'
|
||||
|
||||
export default {
|
||||
label: t('preferences.device.name'),
|
||||
field: 'scrcpy',
|
||||
children: () => {
|
||||
return [
|
||||
{
|
||||
label: t('preferences.device.show-touch.name'),
|
||||
field: '--show-touches',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t('preferences.device.show-touch.placeholder'),
|
||||
tips: t('preferences.device.show-touch.tips'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.device.stay-awake.name'),
|
||||
field: '--stay-awake',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t('preferences.device.stay-awake.placeholder'),
|
||||
tips: t('preferences.device.stay-awake.tips'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.device.control-in-close-screen.name'),
|
||||
field: '--turn-screen-off',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t(
|
||||
'preferences.device.control-in-close-screen.placeholder',
|
||||
),
|
||||
},
|
||||
{
|
||||
label: t('preferences.device.control-end-video.name'),
|
||||
field: '--power-off-on-close',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t('preferences.device.control-end-video.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.device.control-in-stop-charging.name'),
|
||||
field: '--no-power-on',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t(
|
||||
'preferences.device.control-in-stop-charging.placeholder',
|
||||
),
|
||||
tips: t('preferences.device.control-in-stop-charging.tips'),
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
8
src/store/preference/model/index.js
Normal file
8
src/store/preference/model/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
import common from './common/index.js'
|
||||
import video from './video/index.js'
|
||||
import device from './device/index.js'
|
||||
import window from './window/index.js'
|
||||
import audio from './audio/index.js'
|
||||
import record from './record/index.js'
|
||||
|
||||
export default { common, video, device, window, audio, record }
|
27
src/store/preference/model/record/index.js
Normal file
27
src/store/preference/model/record/index.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { t } from '@/locales/index.js'
|
||||
|
||||
export default {
|
||||
label: t('preferences.record.name'),
|
||||
field: 'scrcpy',
|
||||
children: () => {
|
||||
return [
|
||||
{
|
||||
label: t('preferences.record.format.name'),
|
||||
field: '--record-format',
|
||||
type: 'Select',
|
||||
value: 'mp4',
|
||||
placeholder: t('preferences.record.format.placeholder'),
|
||||
options: [
|
||||
{
|
||||
label: 'mp4',
|
||||
value: 'mp4',
|
||||
},
|
||||
{
|
||||
label: 'mkv',
|
||||
value: 'mkv',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
159
src/store/preference/model/video/index.js
Normal file
159
src/store/preference/model/video/index.js
Normal file
@ -0,0 +1,159 @@
|
||||
import { t } from '@/locales/index.js'
|
||||
|
||||
const getDisplayOptions = (display = []) =>
|
||||
display?.map(value => ({ label: value, value })) || []
|
||||
|
||||
export default {
|
||||
label: t('preferences.video.name'),
|
||||
field: 'scrcpy',
|
||||
|
||||
children: ({ display } = {}) => {
|
||||
const displayOptions = display?.length
|
||||
? getDisplayOptions(display)
|
||||
: [
|
||||
{ label: '0', value: '0' },
|
||||
{ label: '1', value: '1' },
|
||||
{ label: '2', value: '2' },
|
||||
]
|
||||
|
||||
return [
|
||||
{
|
||||
label: t('preferences.video.resolution.name'),
|
||||
field: '--max-size',
|
||||
type: 'Input.number',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.resolution.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.bit.name'),
|
||||
field: '--video-bit-rate',
|
||||
type: 'Input',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.bit.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.refresh-rate.name'),
|
||||
field: '--max-fps',
|
||||
type: 'Input.number',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.refresh-rate.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.decoder.name'),
|
||||
field: '--video-codec',
|
||||
type: 'Select',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.decoder.placeholder'),
|
||||
options: [
|
||||
{
|
||||
label: 'h264',
|
||||
value: 'h264',
|
||||
},
|
||||
{
|
||||
label: 'h265',
|
||||
value: 'h265',
|
||||
},
|
||||
{
|
||||
label: 'av1',
|
||||
value: 'av1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.encoder.name'),
|
||||
field: '--video-encoder',
|
||||
type: 'Select',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.encoder.placeholder'),
|
||||
// "[server] INFO: List of video encoders:"
|
||||
// "--video-codec=h264 --video-encoder='OMX.qcom.video.encoder.avc'"
|
||||
// "--video-codec=h264 --video-encoder='c2.android.avc.encoder'"
|
||||
// "--video-codec=h264 --video-encoder='OMX.google.h264.encoder'"
|
||||
// "--video-codec=h265 --video-encoder='OMX.qcom.video.encoder.hevc'"
|
||||
// "--video-codec=h265 --video-encoder='c2.android.hevc.encoder'"
|
||||
options: [
|
||||
{
|
||||
label: 'Android HEVC(H.265) ',
|
||||
value: 'OMX.qcom.video.encoder.avc',
|
||||
},
|
||||
{
|
||||
label: 'Qualcomm HEVC(H.265) ',
|
||||
value: 'c2.android.avc.encoder',
|
||||
},
|
||||
{
|
||||
label: 'Google H.264(AVC)',
|
||||
value: 'OMX.google.h264.encoder',
|
||||
},
|
||||
{
|
||||
label: 'Android AVC(H.264) ',
|
||||
value: 'OMX.qcom.video.encoder.hevc',
|
||||
},
|
||||
{
|
||||
label: 'Qualcomm AVC(H.264)',
|
||||
value: 'c2.android.hevc.encoder',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.screen-rotation.name'),
|
||||
field: '--rotation',
|
||||
type: 'Select',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.screen-rotation.placeholder'),
|
||||
options: [
|
||||
{ label: '0°', value: '0' },
|
||||
{ label: '-90°', value: '1' },
|
||||
{ label: '180°', value: '2' },
|
||||
{ label: '90°', value: '3' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.screen-cropping.name'),
|
||||
field: '--crop',
|
||||
type: 'Input',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.screen-cropping.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.multi-display.name'),
|
||||
field: '--display',
|
||||
type: 'Select',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.multi-display.placeholder'),
|
||||
options: displayOptions,
|
||||
props: {
|
||||
filterable: true,
|
||||
allowCreate: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.video-buffering.name'),
|
||||
field: '--display-buffer',
|
||||
type: 'Input.number',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.video-buffering.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.audio-buffering.name'),
|
||||
field: '--audio-buffer',
|
||||
type: 'Input.number',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.video-buffering.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.receiver-buffering.name'),
|
||||
field: '--v4l2-buffer',
|
||||
type: 'Input.number',
|
||||
value: '',
|
||||
placeholder: t('preferences.video.video-buffering.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.video.disable.name'),
|
||||
field: '--no-video',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t('preferences.video.disable.placeholder'),
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
38
src/store/preference/model/window/index.js
Normal file
38
src/store/preference/model/window/index.js
Normal file
@ -0,0 +1,38 @@
|
||||
import { t } from '@/locales/index.js'
|
||||
|
||||
export default {
|
||||
label: t('preferences.window.name'),
|
||||
field: 'scrcpy',
|
||||
children: () => {
|
||||
return [
|
||||
{
|
||||
label: t('preferences.window.borderless.name'),
|
||||
field: '--window-borderless',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t('preferences.window.borderless.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.window.full-screen.name'),
|
||||
field: '--fullscreen',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t('preferences.window.full-screen.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.window.always-top.name'),
|
||||
field: '--always-on-top',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t('preferences.window.always-top.placeholder'),
|
||||
},
|
||||
{
|
||||
label: t('preferences.window.disable-screen-saver.name'),
|
||||
field: '--disable-screensaver',
|
||||
type: 'Switch',
|
||||
value: false,
|
||||
placeholder: t('preferences.window.disable-screen-saver.placeholder'),
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
@ -94,14 +94,14 @@ export const useScrcpyStore = defineStore({
|
||||
resetDeps(type) {
|
||||
switch (type) {
|
||||
case 'adb':
|
||||
$appStore.set('scrcpy.global.adbPath', '')
|
||||
$appStore.set('scrcpy.common.adbPath', '')
|
||||
break
|
||||
case 'scrcpy':
|
||||
$appStore.set('scrcpy.global.scrcpyPath', '')
|
||||
$appStore.set('scrcpy.common.scrcpyPath', '')
|
||||
break
|
||||
default:
|
||||
$appStore.set('scrcpy.global.adbPath', '')
|
||||
$appStore.set('scrcpy.global.scrcpyPath', '')
|
||||
$appStore.set('scrcpy.common.adbPath', '')
|
||||
$appStore.set('scrcpy.common.scrcpyPath', '')
|
||||
break
|
||||
}
|
||||
this.init()
|
||||
|
@ -5,34 +5,34 @@ export default () => {
|
||||
|
||||
return [
|
||||
{
|
||||
label: t('preferences.custom.file.name'),
|
||||
label: t('preferences.common.file.name'),
|
||||
type: 'input.path',
|
||||
field: 'savePath',
|
||||
value: desktopPath,
|
||||
placeholder: t('preferences.custom.file.placeholder'),
|
||||
tips: t('preferences.custom.file.tips'),
|
||||
placeholder: t('preferences.common.file.placeholder'),
|
||||
tips: t('preferences.common.file.tips'),
|
||||
properties: ['openDirectory'],
|
||||
},
|
||||
{
|
||||
label: t('preferences.custom.adb.name'),
|
||||
label: t('preferences.common.adb.name'),
|
||||
field: 'adbPath',
|
||||
type: 'input.path',
|
||||
value: adbPath,
|
||||
placeholder: t('preferences.custom.adb.placeholder'),
|
||||
tips: t('preferences.custom.adb.tips'),
|
||||
placeholder: t('preferences.common.adb.placeholder'),
|
||||
tips: t('preferences.common.adb.tips'),
|
||||
properties: ['openFile'],
|
||||
filters: [{ name: t('preferences.custom.adb.name'), extensions: ['*'] }],
|
||||
filters: [{ name: t('preferences.common.adb.name'), extensions: ['*'] }],
|
||||
},
|
||||
{
|
||||
label: t('preferences.custom.scrcpy.name'),
|
||||
label: t('preferences.common.scrcpy.name'),
|
||||
field: 'scrcpyPath',
|
||||
type: 'input.path',
|
||||
value: scrcpyPath,
|
||||
placeholder: t('preferences.custom.scrcpy.placeholder'),
|
||||
tips: t('preferences.custom.scrcpy.tips'),
|
||||
placeholder: t('preferences.common.scrcpy.placeholder'),
|
||||
tips: t('preferences.common.scrcpy.tips'),
|
||||
properties: ['openFile'],
|
||||
filters: [
|
||||
{ name: t('preferences.custom.scrcpy.name'), extensions: ['*'] },
|
||||
{ name: t('preferences.common.scrcpy.name'), extensions: ['*'] },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { cloneDeep, keyBy } from 'lodash-es'
|
||||
|
||||
/**
|
||||
* @desc 使用async await 进项进行延时操作
|
||||
@ -37,3 +37,14 @@ export function createProxy(targetObject, methodNames) {
|
||||
return proxyObj
|
||||
}, {})
|
||||
}
|
||||
|
||||
export function keyByValue(data, key = 'key', valueKey = 'value') {
|
||||
const model = keyBy(data, key) || {}
|
||||
|
||||
const value = Object.entries(model).reduce((obj, [modelKey, modelValue]) => {
|
||||
obj[modelKey] = modelValue?.[valueKey]
|
||||
return obj
|
||||
}, {})
|
||||
|
||||
return value
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user