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` 进入开发者工具,并查看是否有任何报错信息。
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 = 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)

View File

@ -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}`)

View File

@ -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,
})

View File

@ -37,8 +37,13 @@ function createWindow() {
}
mainWindow = new BrowserWindow({
// 这里设置的图标仅在开发模式生效,打包后将使用应用程序图标
...(!app.isPackaged
? {
icon,
}
: {}),
show: false,
icon,
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(() => {

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,
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) {

View File

@ -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 = '正在获取设备列表...'

View File

@ -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()

View File

@ -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)
},

View File

@ -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: ['*'] }],
},
]
}