perf: 💄 窗口控制及交互逻辑优化

This commit is contained in:
viarotel 2023-10-24 16:46:51 +08:00
parent c1863848e5
commit 52514e2daf
14 changed files with 137 additions and 23 deletions

View File

@ -189,6 +189,13 @@
4. 按下 `Ctrl` + `Shift` + `I` 进入开发者工具,并查看是否有任何报错信息。 4. 按下 `Ctrl` + `Shift` + `I` 进入开发者工具,并查看是否有任何报错信息。
5. 如果有报错,请截图并在 [反馈问题](https://github.com/viarotel-org/escrcpy/issues) 页面中提交您的问题。 5. 如果有报错,请截图并在 [反馈问题](https://github.com/viarotel-org/escrcpy/issues) 页面中提交您的问题。
### macOS 关闭窗口选择最小化到托盘后顶部右侧状态栏找不到图标
> 这个一般是状态栏图标过多导致无法展示 Escrcpy 的图标 推荐用以下工具解决
- [iBar](https://www.better365.cn/ibar.html)
- [Bartender](https://www.macbartender.com/)
## 获得帮助 ## 获得帮助
> 因为是开源项目 全靠爱发电 所以支持有限 更新节奏不固定 > 因为是开源项目 全靠爱发电 所以支持有限 更新节奏不固定

View File

@ -10,14 +10,31 @@ export default (mainWindow) => {
tray.destroy() tray.destroy()
tray = null tray = null
} }
if (process.platform === 'darwin') {
app.dock.show()
}
mainWindow.show() mainWindow.show()
return true return true
} }
const hideApp = () => {
if (process.platform === 'darwin') {
app.dock.hide()
}
mainWindow.hide()
return true
}
const quitApp = () => { const quitApp = () => {
app.isQuiting = true app.isQuiting = true
app.quit() app.quit()
return true return true
} }
@ -27,7 +44,7 @@ export default (mainWindow) => {
return true return true
} }
else if (response === 1) { else if (response === 1) {
mainWindow.hide() hideApp()
tray = new Tray(trayPath) tray = new Tray(trayPath)

View File

@ -20,10 +20,6 @@ window.addEventListener('beforeunload', () => {
appStore.onDidChange('scrcpy.global.adbPath', async (value, oldValue) => { appStore.onDidChange('scrcpy.global.adbPath', async (value, oldValue) => {
console.log('onDidChange.scrcpy.global.adbPath', value) console.log('onDidChange.scrcpy.global.adbPath', value)
if (!value) {
return false
}
if (value === oldValue) { if (value === oldValue) {
return false return false
} }
@ -37,7 +33,7 @@ appStore.onDidChange('scrcpy.global.adbPath', async (value, oldValue) => {
client = null client = null
} }
client = Adb.createClient({ bin: value }) client = Adb.createClient({ bin: value || adbPath })
}) })
const shell = async command => exec(`${adbPath} ${command}`) const shell = async command => exec(`${adbPath} ${command}`)

View File

@ -4,10 +4,11 @@ import { adbPath, scrcpyPath } from '@electron/configs/index.js'
const shell = async (command, { stdout, stderr } = {}) => { const shell = async (command, { stdout, stderr } = {}) => {
const spawnPath = appStore.get('scrcpy.global.scrcpyPath') || scrcpyPath const spawnPath = appStore.get('scrcpy.global.scrcpyPath') || scrcpyPath
const ADB = appStore.get('scrcpy.global.adbPath') || adbPath
const args = command.split(' ') const args = command.split(' ')
const scrcpyProcess = spawn(spawnPath, args, { const scrcpyProcess = spawn(spawnPath, args, {
env: { ...process.env, ADB: adbPath }, env: { ...process.env, ADB },
shell: true, shell: true,
}) })

View File

@ -37,8 +37,13 @@ function createWindow() {
} }
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
show: false, // 这里设置的图标仅在开发模式生效,打包后将使用应用程序图标
...(!app.isPackaged
? {
icon, icon,
}
: {}),
show: false,
width: 1000, width: 1000,
height: 700, height: 700,
minWidth: 1000, minWidth: 1000,
@ -85,12 +90,20 @@ app.on('window-all-closed', () => {
mainWindow = null mainWindow = null
}) })
// 仅 macOS 有这个事件
app.on('activate', () => { 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) { if (BrowserWindow.getAllWindows().length === 0) {
createWindow() createWindow()
} }
if (app.isHidden()) {
app.show()
app.focus()
}
if (!app.dock.isVisible()) {
app.dock.show()
}
}) })
app.whenReady().then(() => { app.whenReady().then(() => {

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 B

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1008 B

View File

@ -25,6 +25,11 @@ export default {
Preference, Preference,
About, About,
}, },
provide() {
return {
$app: this,
}
},
data() { data() {
return { return {
tabsModel: [ tabsModel: [
@ -42,6 +47,7 @@ export default {
}, },
], ],
activeTab: 'Device', activeTab: 'Device',
renderTab: '',
rendered: true, rendered: true,
} }
}, },
@ -80,15 +86,20 @@ export default {
) )
}, },
isRender(item) { isRender(item) {
if (this.activeTab === item.prop) { if (this.renderTab === item.prop) {
return this.rendered return this.rendered
} }
return true return true
}, },
async reRender() { async reRender(other) {
this.renderTab = other || this.activeTab
this.rendered = false this.rendered = false
await this.$nextTick() await this.$nextTick()
this.rendered = true this.rendered = true
this.renderTab = ''
}, },
async onTabChange(prop) { async onTabChange(prop) {
switch (prop) { switch (prop) {

View File

@ -36,11 +36,11 @@
type="primary" type="primary"
:icon="loading ? '' : 'Refresh'" :icon="loading ? '' : 'Refresh'"
:loading="loading" :loading="loading"
@click="getDeviceData" @click="handleRefresh"
> >
刷新设备 刷新设备
</el-button> </el-button>
<el-button type="warning" icon="RefreshRight" @click="handleReset"> <el-button type="warning" icon="RefreshRight" @click="handleRestart">
重启服务 重启服务
</el-button> </el-button>
</div> </div>
@ -172,6 +172,7 @@ export default {
ControlBar, ControlBar,
Remark, Remark,
}, },
inject: ['$app'],
data() { data() {
const adbCache = storage.get('adbCache') || {} const adbCache = storage.get('adbCache') || {}
return { return {
@ -216,6 +217,35 @@ export default {
scrcpyArgs(...args) { scrcpyArgs(...args) {
return this.$store.scrcpy.getStringConfig(...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() {}, onStdout() {},
toggleRowExpansion(...params) { toggleRowExpansion(...params) {
this.$refs.elTable.toggleRowExpansion(...params) this.$refs.elTable.toggleRowExpansion(...params)
@ -269,6 +299,8 @@ export default {
if (error.message) { if (error.message) {
this.$message.warning(error.message) this.$message.warning(error.message)
} }
this.handleReset()
} }
row.$recordLoading = false row.$recordLoading = false
}, },
@ -289,6 +321,7 @@ export default {
if (error.message) { if (error.message) {
this.$message.warning(error.message) this.$message.warning(error.message)
} }
this.handleReset()
} }
row.$loading = false row.$loading = false
}, },
@ -310,7 +343,7 @@ export default {
onPairSuccess() { onPairSuccess() {
this.handleConnect() this.handleConnect()
}, },
handleReset() { handleRestart() {
this.$electron.ipcRenderer.send('restart-app') this.$electron.ipcRenderer.send('restart-app')
}, },
async handleConnect() { async handleConnect() {
@ -326,7 +359,7 @@ export default {
storage.set('adbCache', this.formData) storage.set('adbCache', this.formData)
} }
catch (error) { catch (error) {
this.handleError(error.message) this.handleError(error?.message || error?.cause?.message || error)
} }
this.connectLoading = false this.connectLoading = false
}, },
@ -339,7 +372,8 @@ export default {
<div>1. IP地址或端口号错误</div> <div>1. IP地址或端口号错误</div>
<div>2. 设备未与当前电脑配对成功</div> <div>2. 设备未与当前电脑配对成功</div>
<div>3. 电脑网络和提供的设备网络IP不在同一个局域网中</div> <div>3. 电脑网络和提供的设备网络IP不在同一个局域网中</div>
<div>4. 其他未知错误</div> <div>4. adb 依赖路径错误</div>
<div>5. 其他未知错误</div>
`, `,
'连接设备失败', '连接设备失败',
{ {
@ -371,7 +405,7 @@ export default {
row.$stopLoading = false row.$stopLoading = false
}, },
async getDeviceData() { async getDeviceData({ resetResolve = false } = {}) {
this.loading = true this.loading = true
await sleep(500) await sleep(500)
try { try {
@ -392,6 +426,10 @@ export default {
this.$message.warning(error?.message || error?.cause?.message) this.$message.warning(error?.message || error?.cause?.message)
} }
this.deviceList = [] this.deviceList = []
if (resetResolve) {
this.handleReset('adb')
}
} }
this.loading = false this.loading = false
this.loadingText = '正在获取设备列表...' this.loadingText = '正在获取设备列表...'

View File

@ -191,6 +191,7 @@ import { useScrcpyStore } from '@/store/index.js'
import LoadingIcon from '@/components/Device/ControlBar/LoadingIcon/index.vue' import LoadingIcon from '@/components/Device/ControlBar/LoadingIcon/index.vue'
export default { export default {
inject: ['$app'],
data() { data() {
const scrcpyStore = useScrcpyStore() const scrcpyStore = useScrcpyStore()

View File

@ -5,6 +5,8 @@ import { replaceIP } from '@/utils/index.js'
const $appStore = window.appStore const $appStore = window.appStore
const { adbPath, scrcpyPath } = window.electron?.configs || {}
function mergeConfig(object, sources, { debug = false } = {}) { function mergeConfig(object, sources, { debug = false } = {}) {
const customizer = (objValue, srcValue) => { const customizer = (objValue, srcValue) => {
if (debug) { if (debug) {
@ -89,6 +91,21 @@ export const useScrcpyStore = defineStore({
this.init() 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) { setScope(value) {
this.scope = replaceIP(value) this.scope = replaceIP(value)
$appStore.set('scrcpy.scope', this.scope) $appStore.set('scrcpy.scope', this.scope)
@ -127,7 +144,20 @@ export const useScrcpyStore = defineStore({
return value return value
}, },
setConfig(data, scope = this.scope) { 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) this.init(scope)
}, },

View File

@ -17,9 +17,9 @@ export default () => {
type: 'input.path', type: 'input.path',
value: adbPath, value: adbPath,
tips: '用于连接设备的 adb 的地址,注意:该选项不受针对于单个设备配置的影响', tips: '用于连接设备的 adb 的地址,注意:该选项不受针对于单个设备配置的影响',
placeholder: '请选择 adb', placeholder: '请设置 adb 路径',
properties: ['openFile'], properties: ['openFile'],
filters: [{ name: '请选择 adb', extensions: ['*'] }], filters: [{ name: '请设置 adb 路径', extensions: ['*'] }],
}, },
{ {
label: 'scrcpy 路径', label: 'scrcpy 路径',
@ -27,9 +27,9 @@ export default () => {
type: 'input.path', type: 'input.path',
value: scrcpyPath, value: scrcpyPath,
tips: '用于控制设备的 scrcpy 的地址,注意:该选项不受针对于单个设备配置的影响', tips: '用于控制设备的 scrcpy 的地址,注意:该选项不受针对于单个设备配置的影响',
placeholder: '请选择 scrcpy', placeholder: '请设置 scrcpy 路径',
properties: ['openFile'], properties: ['openFile'],
filters: [{ name: '请选择 scrcpy', extensions: ['*'] }], filters: [{ name: '请设置 scrcpy 路径', extensions: ['*'] }],
}, },
] ]
} }