mirror of
https://github.com/viarotel-org/escrcpy.git
synced 2024-11-14 10:47:55 +01:00
perf: ♻️ Optimize terminal performance
This commit is contained in:
parent
5b6b8d1150
commit
d3afc4ba62
@ -1,5 +1,5 @@
|
||||
import util from 'node:util'
|
||||
import child_process from 'node:child_process'
|
||||
import { exec as _exec, spawn } from 'node:child_process'
|
||||
import path from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
import dayjs from 'dayjs'
|
||||
@ -8,7 +8,7 @@ import appStore from '@electron/helpers/store.js'
|
||||
import { adbPath } from '@electron/configs/index.js'
|
||||
import { uniq } from 'lodash-es'
|
||||
|
||||
const exec = util.promisify(child_process.exec)
|
||||
const exec = util.promisify(_exec)
|
||||
|
||||
let client = null
|
||||
|
||||
@ -37,7 +37,66 @@ appStore.onDidChange('common.adbPath', async (value, oldValue) => {
|
||||
client = Adb.createClient({ bin: value || adbPath })
|
||||
})
|
||||
|
||||
const shell = async command => exec(`${adbPath} ${command}`)
|
||||
const shell = async (command) => {
|
||||
const execPath = appStore.get('common.adbPath') || adbPath
|
||||
return exec(`${execPath} ${command}`, {
|
||||
env: { ...process.env },
|
||||
shell: true,
|
||||
})
|
||||
}
|
||||
|
||||
const spawnShell = async (command, { stdout, stderr } = {}) => {
|
||||
const spawnPath = appStore.get('common.adbPath') || adbPath
|
||||
const args = command.split(' ')
|
||||
|
||||
console.log('adb.spawnShell.spawnPath', spawnPath)
|
||||
console.log('adb.spawnShell.args', args)
|
||||
|
||||
const spawnProcess = spawn(`"${spawnPath}"`, args, {
|
||||
env: { ...process.env },
|
||||
shell: true,
|
||||
encoding: 'utf8',
|
||||
})
|
||||
|
||||
spawnProcess.stdout.on('data', (data) => {
|
||||
const stringData = data.toString()
|
||||
|
||||
console.log('spawnProcess.stdout.data:', stringData)
|
||||
|
||||
if (stdout) {
|
||||
stdout(stringData, spawnProcess)
|
||||
}
|
||||
})
|
||||
|
||||
let lastStderr = ''
|
||||
spawnProcess.stderr.on('data', (data) => {
|
||||
const stringData = data.toString()
|
||||
|
||||
lastStderr = stringData
|
||||
|
||||
console.error('spawnProcess.stderr.data:', stringData)
|
||||
|
||||
if (stderr) {
|
||||
stderr(stringData, spawnProcess)
|
||||
}
|
||||
})
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
spawnProcess.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
resolve()
|
||||
}
|
||||
else {
|
||||
reject(new Error(lastStderr || `Command failed with code ${code}`))
|
||||
}
|
||||
})
|
||||
|
||||
spawnProcess.on('error', (err) => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const getDevices = async () => client.listDevicesWithPaths()
|
||||
const deviceShell = async (id, command) => {
|
||||
const res = await client.getDevice(id).shell(command).then(Adb.util.readAll)
|
||||
@ -193,6 +252,7 @@ export default () => {
|
||||
|
||||
return {
|
||||
shell,
|
||||
spawnShell,
|
||||
getDevices,
|
||||
deviceShell,
|
||||
kill,
|
||||
|
@ -46,9 +46,12 @@ const shell = async (command, { debug = false, stdout, stderr } = {}) => {
|
||||
}
|
||||
})
|
||||
|
||||
let lastStderr = ''
|
||||
gnirehtetProcess.stderr.on('data', (data) => {
|
||||
const stringData = data.toString()
|
||||
|
||||
lastStderr = stringData
|
||||
|
||||
if (debug) {
|
||||
console.error(`${command}.gnirehtet.process.stderr.data:`, stringData)
|
||||
}
|
||||
|
@ -33,9 +33,12 @@ const shell = async (command, { stdout, stderr } = {}) => {
|
||||
}
|
||||
})
|
||||
|
||||
let lastStderr = ''
|
||||
scrcpyProcess.stderr.on('data', (data) => {
|
||||
const stringData = data.toString()
|
||||
|
||||
lastStderr = stringData
|
||||
|
||||
console.error('scrcpyProcess.stderr.data:', stringData)
|
||||
|
||||
if (stderr) {
|
||||
@ -49,7 +52,7 @@ const shell = async (command, { stdout, stderr } = {}) => {
|
||||
resolve()
|
||||
}
|
||||
else {
|
||||
reject(new Error(`Command failed with code ${code}`))
|
||||
reject(new Error(lastStderr || `Command failed with code ${code}`))
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -0,0 +1,44 @@
|
||||
import { debounce } from 'lodash-es'
|
||||
import { createStderr, createStdout, textFormatter } from 'vue-command'
|
||||
import { useFixCursor } from './helper.js'
|
||||
|
||||
const $adb = window.adbkit
|
||||
|
||||
export function useAdb({ vShell, history, loading } = {}) {
|
||||
const adb = async (args) => {
|
||||
loading.value = true
|
||||
|
||||
const command = args.slice(1).join(' ')
|
||||
|
||||
const appendToHistory = debounce(vShell.value.appendToHistory, 500)
|
||||
|
||||
let stdoutText = ''
|
||||
let stderrText = ''
|
||||
$adb.spawnShell(command, {
|
||||
stdout(text) {
|
||||
loading.value = false
|
||||
|
||||
stdoutText += text
|
||||
|
||||
useFixCursor(history)
|
||||
|
||||
appendToHistory(createStdout(stdoutText))
|
||||
},
|
||||
stderr(text) {
|
||||
loading.value = false
|
||||
|
||||
stderrText += text
|
||||
|
||||
useFixCursor(history)
|
||||
|
||||
appendToHistory(createStderr(stderrText))
|
||||
},
|
||||
})
|
||||
|
||||
return textFormatter('Waiting...')
|
||||
}
|
||||
|
||||
return {
|
||||
adb,
|
||||
}
|
||||
}
|
@ -1,15 +1,9 @@
|
||||
import { debounce } from 'lodash-es'
|
||||
import { createStderr, createStdout, textFormatter } from 'vue-command'
|
||||
import { useFixCursor } from './helper.js'
|
||||
|
||||
const $gnirehtet = window.gnirehtet
|
||||
|
||||
const fixCursor = (history) => {
|
||||
const length = history.value.length
|
||||
if (history.value[length - 1]?.__name === 'VueCommandQuery') {
|
||||
history.value.splice(length - 1, 1, textFormatter('Waiting...'))
|
||||
}
|
||||
}
|
||||
|
||||
export function useGnirehtet({ vShell, history, loading } = {}) {
|
||||
const gnirehtet = async (args) => {
|
||||
loading.value = true
|
||||
@ -26,7 +20,7 @@ export function useGnirehtet({ vShell, history, loading } = {}) {
|
||||
|
||||
stdoutText += text
|
||||
|
||||
fixCursor(history)
|
||||
useFixCursor(history)
|
||||
|
||||
appendToHistory(createStdout(stdoutText))
|
||||
},
|
||||
@ -35,13 +29,13 @@ export function useGnirehtet({ vShell, history, loading } = {}) {
|
||||
|
||||
stderrText += text
|
||||
|
||||
fixCursor(history)
|
||||
useFixCursor(history)
|
||||
|
||||
appendToHistory(createStderr(stderrText))
|
||||
},
|
||||
})
|
||||
|
||||
return textFormatter('Loading...')
|
||||
return textFormatter('Waiting...')
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -0,0 +1,8 @@
|
||||
import { textFormatter } from 'vue-command'
|
||||
|
||||
export function useFixCursor(history) {
|
||||
const length = history.value.length
|
||||
if (history.value[length - 1]?.__name === 'VueCommandQuery') {
|
||||
history.value.splice(length - 1, 1, textFormatter('Waiting...'))
|
||||
}
|
||||
}
|
@ -1,15 +1,9 @@
|
||||
import { debounce } from 'lodash-es'
|
||||
import { createStderr, createStdout, textFormatter } from 'vue-command'
|
||||
import { useFixCursor } from './helper.js'
|
||||
|
||||
const $scrcpy = window.scrcpy
|
||||
|
||||
const fixCursor = (history) => {
|
||||
const length = history.value.length
|
||||
if (history.value[length - 1]?.__name === 'VueCommandQuery') {
|
||||
history.value.splice(length - 1, 1, textFormatter('Waiting...'))
|
||||
}
|
||||
}
|
||||
|
||||
export function useScrcpy({ vShell, history, loading } = {}) {
|
||||
const scrcpy = async (args) => {
|
||||
loading.value = true
|
||||
@ -22,11 +16,12 @@ export function useScrcpy({ vShell, history, loading } = {}) {
|
||||
let stderrText = ''
|
||||
$scrcpy.shell(command, {
|
||||
stdout(text) {
|
||||
console.log('history', history)
|
||||
loading.value = false
|
||||
|
||||
stdoutText += text
|
||||
|
||||
fixCursor(history)
|
||||
useFixCursor(history)
|
||||
|
||||
appendToHistory(createStdout(stdoutText))
|
||||
},
|
||||
@ -35,13 +30,13 @@ export function useScrcpy({ vShell, history, loading } = {}) {
|
||||
|
||||
stderrText += text
|
||||
|
||||
fixCursor(history)
|
||||
useFixCursor(history)
|
||||
|
||||
appendToHistory(createStderr(stderrText))
|
||||
},
|
||||
})
|
||||
|
||||
return textFormatter('Loading...')
|
||||
return textFormatter('Waiting...')
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -3,32 +3,34 @@
|
||||
v-model="visible"
|
||||
width="80%"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
class="overflow-hidden rounded-xl el-dialog-headless"
|
||||
:close-on-press-escape="true"
|
||||
class="overflow-hidden rounded-md el-dialog-headless dark:border dark:border-gray-700"
|
||||
@open="onOpen"
|
||||
>
|
||||
<el-icon
|
||||
class="cursor-pointer absolute top-2 right-2 w-8 h-8 flex items-center justify-center text-gray-200 hover:bg-gray-700 !active:bg-red-600 rounded"
|
||||
class="cursor-pointer absolute top-2 right-2 w-8 h-8 flex items-center justify-center hover:bg-gray-200 dark:text-gray-200 dark:hover:bg-gray-700 !active:bg-red-600 !active:text-gray-200 rounded-md"
|
||||
@click="hide"
|
||||
>
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
|
||||
<VueCommand
|
||||
v-if="visible"
|
||||
v-if="renderShell"
|
||||
:ref="(value) => (vShell = value)"
|
||||
v-model:history="history"
|
||||
:dispatched-queries="dispatchedQueries"
|
||||
:commands="commands"
|
||||
hide-bar
|
||||
show-help
|
||||
help-text="Type in help"
|
||||
:help-timeout="3500"
|
||||
:help-timeout="3000"
|
||||
:invert="invert"
|
||||
class=""
|
||||
:dispatched-queries="dispatchedQueries"
|
||||
@update:dispatched-queries="onDispatchedQueriesUpdate"
|
||||
>
|
||||
<template #prompt>
|
||||
<div class="flex items-center pr-2">
|
||||
<span class="">escrcpy~$</span>
|
||||
<span class="">Escrcpy~$</span>
|
||||
</div>
|
||||
</template>
|
||||
</VueCommand>
|
||||
@ -36,7 +38,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref } from 'vue'
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import VueCommand, {
|
||||
createQuery,
|
||||
createStdout,
|
||||
@ -53,8 +55,9 @@ export default {
|
||||
},
|
||||
setup() {
|
||||
const vShell = ref(null)
|
||||
const history = ref([createQuery()])
|
||||
const history = shallowRef([createQuery()])
|
||||
const loading = ref(false)
|
||||
const renderShell = ref(false)
|
||||
const dispatchedQueries = ref(new Set([]))
|
||||
|
||||
const { adb } = useAdb({ vShell, history, loading })
|
||||
@ -76,7 +79,17 @@ export default {
|
||||
return createStdout(listFormatter('Supported Commands:', ...commandList))
|
||||
}
|
||||
|
||||
dispatchedQueries.value = new Set(Object.keys(commands.value))
|
||||
dispatchedQueries.value = new Set([
|
||||
...(window.appStore.get('terminal.dispatchedQueries') || []),
|
||||
...Object.keys(commands.value),
|
||||
])
|
||||
|
||||
const onOpen = () => {
|
||||
console.log('vShell.value', vShell.value)
|
||||
console.log('history.value', history.value)
|
||||
|
||||
renderShell.value = true
|
||||
}
|
||||
|
||||
return {
|
||||
vShell,
|
||||
@ -84,6 +97,8 @@ export default {
|
||||
history,
|
||||
commands,
|
||||
dispatchedQueries,
|
||||
onOpen,
|
||||
renderShell,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@ -91,22 +106,44 @@ export default {
|
||||
visible: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
invert() {
|
||||
return this.$store.theme.value !== 'dark'
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'vShell.signals': {
|
||||
handler(value) {
|
||||
console.log('vShell.signals.value', value)
|
||||
|
||||
value.off('SIGINT')
|
||||
|
||||
value.on('SIGINT', () => {
|
||||
console.log('vShell.signals.on.SIGINT')
|
||||
this.onCtrlC()
|
||||
})
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
this.visible = true
|
||||
},
|
||||
|
||||
hide() {
|
||||
this.visible = false
|
||||
},
|
||||
async onOpen() {
|
||||
console.log('vShell', this.vShell)
|
||||
|
||||
this.vShell.signals.off('SIGINT')
|
||||
onDispatchedQueriesUpdate(value) {
|
||||
console.log('onDispatchedQueriesUpdate.value', value)
|
||||
|
||||
this.vShell.signals.on('SIGINT', () => {
|
||||
console.log('vShell.signals.on.SIGINT')
|
||||
this.$gnirehtet.shell('stop')
|
||||
})
|
||||
this.$appStore.set('terminal.dispatchedQueries', Array.from(value))
|
||||
|
||||
this.dispatchedQueries = value
|
||||
},
|
||||
|
||||
onCtrlC() {
|
||||
window.gnirehtet.shell('stop')
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -282,15 +282,21 @@ export default {
|
||||
args: this.scrcpyArgs(row.id, { isRecord: true }),
|
||||
stdout: this.onStdout,
|
||||
})
|
||||
this.handleRecordSuccess(savePath)
|
||||
}
|
||||
catch (error) {
|
||||
console.warn(error)
|
||||
|
||||
if (error.message) {
|
||||
this.$message.warning(error.message)
|
||||
}
|
||||
|
||||
this.handleReset()
|
||||
}
|
||||
|
||||
row.$recordLoading = false
|
||||
},
|
||||
async handleRecordSuccess(savePath) {
|
||||
try {
|
||||
await this.$confirm(
|
||||
this.$t('device.record.success.message'),
|
||||
@ -311,8 +317,6 @@ export default {
|
||||
catch (error) {
|
||||
console.warn(error)
|
||||
}
|
||||
|
||||
row.$recordLoading = false
|
||||
},
|
||||
async handleMirror(row) {
|
||||
row.$loading = true
|
||||
|
Loading…
Reference in New Issue
Block a user