perf: 💄 窗口控制及交互逻辑优化
@ -189,6 +189,13 @@
|
||||
4. 按下 `Ctrl` + `Shift` + `I` 进入开发者工具,并查看是否有任何报错信息。
|
||||
5. 如果有报错,请截图并在 [反馈问题](https://github.com/viarotel-org/escrcpy/issues) 页面中提交您的问题。
|
||||
|
||||
### macOS 关闭窗口选择最小化到托盘后顶部右侧状态栏找不到图标
|
||||
|
||||
> 这个一般是状态栏图标过多导致无法展示 Escrcpy 的图标 推荐用以下工具解决
|
||||
|
||||
- [iBar](https://www.better365.cn/ibar.html)
|
||||
- [Bartender](https://www.macbartender.com/)
|
||||
|
||||
## 获得帮助
|
||||
|
||||
> 因为是开源项目 全靠爱发电 所以支持有限 更新节奏不固定
|
||||
|
@ -10,14 +10,31 @@ export default (mainWindow) => {
|
||||
tray.destroy()
|
||||
tray = null
|
||||
}
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
app.dock.show()
|
||||
}
|
||||
|
||||
mainWindow.show()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const hideApp = () => {
|
||||
if (process.platform === 'darwin') {
|
||||
app.dock.hide()
|
||||
}
|
||||
|
||||
mainWindow.hide()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const quitApp = () => {
|
||||
app.isQuiting = true
|
||||
|
||||
app.quit()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@ -27,7 +44,7 @@ export default (mainWindow) => {
|
||||
return true
|
||||
}
|
||||
else if (response === 1) {
|
||||
mainWindow.hide()
|
||||
hideApp()
|
||||
|
||||
tray = new Tray(trayPath)
|
||||
|
||||
|
@ -20,10 +20,6 @@ window.addEventListener('beforeunload', () => {
|
||||
appStore.onDidChange('scrcpy.global.adbPath', async (value, oldValue) => {
|
||||
console.log('onDidChange.scrcpy.global.adbPath', value)
|
||||
|
||||
if (!value) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (value === oldValue) {
|
||||
return false
|
||||
}
|
||||
@ -37,7 +33,7 @@ appStore.onDidChange('scrcpy.global.adbPath', async (value, oldValue) => {
|
||||
client = null
|
||||
}
|
||||
|
||||
client = Adb.createClient({ bin: value })
|
||||
client = Adb.createClient({ bin: value || adbPath })
|
||||
})
|
||||
|
||||
const shell = async command => exec(`${adbPath} ${command}`)
|
||||
|
@ -4,10 +4,11 @@ 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 args = command.split(' ')
|
||||
|
||||
const scrcpyProcess = spawn(spawnPath, args, {
|
||||
env: { ...process.env, ADB: adbPath },
|
||||
env: { ...process.env, ADB },
|
||||
shell: true,
|
||||
})
|
||||
|
||||
|
@ -37,8 +37,13 @@ function createWindow() {
|
||||
}
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
show: false,
|
||||
// 这里设置的图标仅在开发模式生效,打包后将使用应用程序图标
|
||||
...(!app.isPackaged
|
||||
? {
|
||||
icon,
|
||||
}
|
||||
: {}),
|
||||
show: false,
|
||||
width: 1000,
|
||||
height: 700,
|
||||
minWidth: 1000,
|
||||
@ -85,12 +90,20 @@ app.on('window-all-closed', () => {
|
||||
mainWindow = null
|
||||
})
|
||||
|
||||
// 仅 macOS 有这个事件
|
||||
app.on('activate', () => {
|
||||
// On OS X it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
|
||||
if (app.isHidden()) {
|
||||
app.show()
|
||||
app.focus()
|
||||
}
|
||||
|
||||
if (!app.dock.isVisible()) {
|
||||
app.dock.show()
|
||||
}
|
||||
})
|
||||
|
||||
app.whenReady().then(() => {
|
||||
|
BIN
electron/resources/extra/tray-raw.png
Normal file
After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 226 B After Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 445 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1008 B |
15
src/App.vue
@ -25,6 +25,11 @@ export default {
|
||||
Preference,
|
||||
About,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
$app: this,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabsModel: [
|
||||
@ -42,6 +47,7 @@ export default {
|
||||
},
|
||||
],
|
||||
activeTab: 'Device',
|
||||
renderTab: '',
|
||||
rendered: true,
|
||||
}
|
||||
},
|
||||
@ -80,15 +86,20 @@ export default {
|
||||
)
|
||||
},
|
||||
isRender(item) {
|
||||
if (this.activeTab === item.prop) {
|
||||
if (this.renderTab === item.prop) {
|
||||
return this.rendered
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
async reRender() {
|
||||
async reRender(other) {
|
||||
this.renderTab = other || this.activeTab
|
||||
|
||||
this.rendered = false
|
||||
await this.$nextTick()
|
||||
this.rendered = true
|
||||
|
||||
this.renderTab = ''
|
||||
},
|
||||
async onTabChange(prop) {
|
||||
switch (prop) {
|
||||
|
@ -36,11 +36,11 @@
|
||||
type="primary"
|
||||
:icon="loading ? '' : 'Refresh'"
|
||||
:loading="loading"
|
||||
@click="getDeviceData"
|
||||
@click="handleRefresh"
|
||||
>
|
||||
刷新设备
|
||||
</el-button>
|
||||
<el-button type="warning" icon="RefreshRight" @click="handleReset">
|
||||
<el-button type="warning" icon="RefreshRight" @click="handleRestart">
|
||||
重启服务
|
||||
</el-button>
|
||||
</div>
|
||||
@ -172,6 +172,7 @@ export default {
|
||||
ControlBar,
|
||||
Remark,
|
||||
},
|
||||
inject: ['$app'],
|
||||
data() {
|
||||
const adbCache = storage.get('adbCache') || {}
|
||||
return {
|
||||
@ -216,6 +217,35 @@ export default {
|
||||
scrcpyArgs(...args) {
|
||||
return this.$store.scrcpy.getStringConfig(...args)
|
||||
},
|
||||
handleRefresh() {
|
||||
this.getDeviceData({ resetResolve: true })
|
||||
},
|
||||
async handleReset(depType = 'scrcpy') {
|
||||
try {
|
||||
await this.$confirm(
|
||||
`
|
||||
<div>通常情况下,这可能是因为更新 Escrcpy 后,缓存的依赖配置不兼容所导致的,是否重置依赖配置?</div>
|
||||
<div class="text-red-500">注意:重置后,之前保存的依赖配置将会被清除,因此建议在执行重置操作之前备份您的配置。</div>
|
||||
`,
|
||||
'操作失败',
|
||||
{
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: '重置依赖配置',
|
||||
cancelButtonText: '取消',
|
||||
closeOnClickModal: false,
|
||||
type: 'warning',
|
||||
},
|
||||
)
|
||||
this.$store.scrcpy.resetDeps(depType)
|
||||
this.$app.reRender('Preference')
|
||||
this.$message.success('操作成功,请重新尝试。')
|
||||
}
|
||||
catch (error) {
|
||||
if (error.message) {
|
||||
console.warn(error.message)
|
||||
}
|
||||
}
|
||||
},
|
||||
onStdout() {},
|
||||
toggleRowExpansion(...params) {
|
||||
this.$refs.elTable.toggleRowExpansion(...params)
|
||||
@ -269,6 +299,8 @@ export default {
|
||||
if (error.message) {
|
||||
this.$message.warning(error.message)
|
||||
}
|
||||
|
||||
this.handleReset()
|
||||
}
|
||||
row.$recordLoading = false
|
||||
},
|
||||
@ -289,6 +321,7 @@ export default {
|
||||
if (error.message) {
|
||||
this.$message.warning(error.message)
|
||||
}
|
||||
this.handleReset()
|
||||
}
|
||||
row.$loading = false
|
||||
},
|
||||
@ -310,7 +343,7 @@ export default {
|
||||
onPairSuccess() {
|
||||
this.handleConnect()
|
||||
},
|
||||
handleReset() {
|
||||
handleRestart() {
|
||||
this.$electron.ipcRenderer.send('restart-app')
|
||||
},
|
||||
async handleConnect() {
|
||||
@ -326,7 +359,7 @@ export default {
|
||||
storage.set('adbCache', this.formData)
|
||||
}
|
||||
catch (error) {
|
||||
this.handleError(error.message)
|
||||
this.handleError(error?.message || error?.cause?.message || error)
|
||||
}
|
||||
this.connectLoading = false
|
||||
},
|
||||
@ -339,7 +372,8 @@ export default {
|
||||
<div>1. IP地址或端口号错误</div>
|
||||
<div>2. 设备未与当前电脑配对成功</div>
|
||||
<div>3. 电脑网络和提供的设备网络IP不在同一个局域网中</div>
|
||||
<div>4. 其他未知错误</div>
|
||||
<div>4. adb 依赖路径错误</div>
|
||||
<div>5. 其他未知错误</div>
|
||||
`,
|
||||
'连接设备失败',
|
||||
{
|
||||
@ -371,7 +405,7 @@ export default {
|
||||
row.$stopLoading = false
|
||||
},
|
||||
|
||||
async getDeviceData() {
|
||||
async getDeviceData({ resetResolve = false } = {}) {
|
||||
this.loading = true
|
||||
await sleep(500)
|
||||
try {
|
||||
@ -392,6 +426,10 @@ export default {
|
||||
this.$message.warning(error?.message || error?.cause?.message)
|
||||
}
|
||||
this.deviceList = []
|
||||
|
||||
if (resetResolve) {
|
||||
this.handleReset('adb')
|
||||
}
|
||||
}
|
||||
this.loading = false
|
||||
this.loadingText = '正在获取设备列表...'
|
||||
|
@ -191,6 +191,7 @@ import { useScrcpyStore } from '@/store/index.js'
|
||||
import LoadingIcon from '@/components/Device/ControlBar/LoadingIcon/index.vue'
|
||||
|
||||
export default {
|
||||
inject: ['$app'],
|
||||
data() {
|
||||
const scrcpyStore = useScrcpyStore()
|
||||
|
||||
|
@ -5,6 +5,8 @@ import { replaceIP } from '@/utils/index.js'
|
||||
|
||||
const $appStore = window.appStore
|
||||
|
||||
const { adbPath, scrcpyPath } = window.electron?.configs || {}
|
||||
|
||||
function mergeConfig(object, sources, { debug = false } = {}) {
|
||||
const customizer = (objValue, srcValue) => {
|
||||
if (debug) {
|
||||
@ -89,6 +91,21 @@ export const useScrcpyStore = defineStore({
|
||||
|
||||
this.init()
|
||||
},
|
||||
resetDeps(type) {
|
||||
switch (type) {
|
||||
case 'adb':
|
||||
$appStore.set('scrcpy.global.adbPath', '')
|
||||
break
|
||||
case 'scrcpy':
|
||||
$appStore.set('scrcpy.global.scrcpyPath', '')
|
||||
break
|
||||
default:
|
||||
$appStore.set('scrcpy.global.adbPath', '')
|
||||
$appStore.set('scrcpy.global.scrcpyPath', '')
|
||||
break
|
||||
}
|
||||
this.init()
|
||||
},
|
||||
setScope(value) {
|
||||
this.scope = replaceIP(value)
|
||||
$appStore.set('scrcpy.scope', this.scope)
|
||||
@ -127,7 +144,20 @@ export const useScrcpyStore = defineStore({
|
||||
return value
|
||||
},
|
||||
setConfig(data, scope = this.scope) {
|
||||
$appStore.set(`scrcpy.${replaceIP(scope)}`, { ...data })
|
||||
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
|
||||
}
|
||||
|
||||
$appStore.set(`scrcpy.${replaceIP(scope)}`, cloneData)
|
||||
|
||||
this.init(scope)
|
||||
},
|
||||
|
@ -17,9 +17,9 @@ export default () => {
|
||||
type: 'input.path',
|
||||
value: adbPath,
|
||||
tips: '用于连接设备的 adb 的地址,注意:该选项不受针对于单个设备配置的影响',
|
||||
placeholder: '请选择 adb',
|
||||
placeholder: '请设置 adb 路径',
|
||||
properties: ['openFile'],
|
||||
filters: [{ name: '请选择 adb', extensions: ['*'] }],
|
||||
filters: [{ name: '请设置 adb 路径', extensions: ['*'] }],
|
||||
},
|
||||
{
|
||||
label: 'scrcpy 路径',
|
||||
@ -27,9 +27,9 @@ export default () => {
|
||||
type: 'input.path',
|
||||
value: scrcpyPath,
|
||||
tips: '用于控制设备的 scrcpy 的地址,注意:该选项不受针对于单个设备配置的影响',
|
||||
placeholder: '请选择 scrcpy',
|
||||
placeholder: '请设置 scrcpy 路径',
|
||||
properties: ['openFile'],
|
||||
filters: [{ name: '请选择 scrcpy', extensions: ['*'] }],
|
||||
filters: [{ name: '请设置 scrcpy 路径', extensions: ['*'] }],
|
||||
},
|
||||
]
|
||||
}
|
||||
|