perf: 🚀 Add File push function

This commit is contained in:
viarotel 2023-11-09 16:17:56 +08:00
parent b40bdcfd7d
commit 70f8b469b9
10 changed files with 165 additions and 18 deletions

View File

@ -175,12 +175,13 @@ Windows 及 Linux 端内部集成了 Gnirehtet 用于提供 PC 到安卓设
11. 添加 Gnirehtet 反向供网功能 ✅
12. 添加新的相机镜像相关功能 ✅
13. 更好的多屏协同 ✅
14. 设备交互栏添加更多功能:文件传输、旋转屏幕、音频控制等功能 🚧
14. 设备交互栏添加更多功能:文件推送、旋转屏幕、音频控制等功能 ✅
15. 支持批量连接历史设备功能 🚧
16. 支持对设备进行分组,以及按组进行批量操作 🚧
17. 添加独立的剪切板同步功能 🚧
18. 支持自定义执行 Adb 脚本 🚧
19. 添加对游戏的增强功能,如游戏键位映射 🚧
16. 添加独立的剪切板同步功能 🚧
17. 支持通过界面从设备下载选中的文件 🚧
18. 支持对设备进行分组,以及按组进行批量操作 🚧
19. 支持自定义执行 Adb 脚本 🚧
20. 添加对游戏的增强功能,如游戏键位映射 🚧
## 常见问题

View File

@ -173,12 +173,13 @@ Refer to [scrcpy/doc/shortcuts](https://github.com/Genymobile/scrcpy/blob/master
11. Add Gnirehtet reverse network function ✅
12. Add new camera mirror related features ✅
13. Better multi -screen collaboration ✅
14. Add more features to device interaction bar: file transfer, screen rotation, audio control etc 🚧
14. Add more features to device interaction bar: file push, screen rotation, audio control etc ✅
15. Support bulk connecting to historical devices 🚧
16. Support grouping devices and bulk operations by group 🚧
17. Add standalone clipboard sync feature 🚧
18. Support custom Adb script execution 🚧
19. Add game enhancement features such as game keyboard mapping 🚧
16. Add standalone clipboard sync feature 🚧
17. Support GUI-based selective file downloads from devices 🚧
18. Support grouping devices and bulk operations by group 🚧
19. Support custom Adb script execution 🚧
20. Add game enhancement features such as game keyboard mapping 🚧
## FAQ

View File

@ -132,6 +132,30 @@ const clearOverlayDisplayDevices = async (deviceId) => {
)
}
const push = async (
id,
filePath,
{ progress, savePath = `/sdcard/Download/${path.basename(filePath)}` } = {},
) => {
const res = await client.getDevice(id).push(filePath, savePath)
return new Promise((resolve, reject) => {
res.on('progress', (stats) => {
console.log('adb.push.progress', stats)
progress?.(stats)
})
res.on('end', (ret) => {
resolve(ret)
})
res.on('error', (err) => {
reject(err)
})
})
}
const watch = async (callback) => {
const tracker = await client.trackDevices()
tracker.on('add', async (ret) => {
@ -182,6 +206,7 @@ export default () => {
version,
display,
clearOverlayDisplayDevices,
push,
watch,
}
}

View File

@ -0,0 +1,98 @@
<template>
<el-dropdown :hide-on-click="false">
<div class="">
<slot :loading="loading" />
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="handlePush">
{{ $t("device.control.file.push") }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script>
export default {
props: {
device: {
type: Object,
default: () => ({}),
},
},
data() {
return {
loading: false,
}
},
methods: {
async handlePush() {
this.loading = true
let files = null
try {
files = await this.$electron.ipcRenderer.invoke('show-open-dialog', {
properties: ['openFile', 'multiSelections'],
filters: [
{
name: this.$t('device.control.file.push.placeholder'),
extensions: ['*'],
},
],
})
}
catch (error) {
if (error.message) {
this.$message.warning(error.message)
}
}
if (!files) {
this.loading = false
return false
}
let failCount = 0
for (let index = 0; index < files.length; index++) {
const item = files[index]
await this.$adb.push(this.device.id, item).catch((e) => {
console.warn(e)
++failCount
})
}
this.loading = false
const totalCount = files.length
const successCount = totalCount - failCount
if (successCount) {
if (totalCount > 1) {
this.$message.success(
this.$t('device.control.file.push.success', {
deviceName: this.device.$name,
totalCount,
successCount,
failCount,
}),
)
}
else {
this.$message.success(
this.$t('device.control.file.push.success.single', {
deviceName: this.device.$name,
}),
)
}
return
}
this.$message.warning(this.$t('device.control.file.push.error'))
},
},
}
</script>
<style></style>

View File

@ -41,7 +41,9 @@ export default {
try {
await this.$gnirehtet.run(device.id)
await sleep()
this.$message.success(this.$t('device.control.gnirehtet.success'))
this.$message.success(
this.$t('device.control.gnirehtet.start.success'),
)
}
catch (error) {
this.$message.warning(error.message || 'Start service failure')

View File

@ -52,6 +52,7 @@ import Gnirehtet from './Gnirehtet/index.vue'
import MirrorGroup from './MirrorGroup/index.vue'
import Rotation from './Rotation/index.vue'
import Volume from './Volume/index.vue'
import FileManage from './FileManage/index.vue'
export default {
components: {
@ -61,6 +62,7 @@ export default {
MirrorGroup,
Rotation,
Volume,
FileManage,
},
props: {
device: {
@ -113,7 +115,6 @@ export default {
label: 'device.control.capture',
elIcon: 'Crop',
component: 'Screenshot',
tips: '',
},
{
label: 'device.control.reboot',
@ -124,7 +125,11 @@ export default {
label: 'device.control.install',
svgIcon: 'install',
component: 'AppInstall',
tips: '',
},
{
label: 'device.control.file.name',
svgIcon: 'file-send',
component: 'FileManage',
},
{
label: 'device.control.gnirehtet',

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><g fill="none"><path d="M24 0v24H0V0h24ZM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018Zm.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022Zm-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01l-.184-.092Z"/><path fill="currentColor" d="M9.52 3a2 2 0 0 1 1.561.75l1.4 1.75H20a2 2 0 0 1 2 2V19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5.52Zm0 2H4v14h16V7.5h-7.52a2 2 0 0 1-1.561-.75L9.519 5Zm3.187 5.173l2.121 2.121a1 1 0 1 1-1.414 1.414L13 13.294V16a1 1 0 1 1-2 0v-2.706l-.414.414a1 1 0 1 1-1.414-1.414l2.12-2.121a1 1 0 0 1 1.415 0Z"/></g></svg>

After

Width:  |  Height:  |  Size: 1013 B

View File

@ -1 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1697530402297" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1513" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M56.888889 284.444444h853.333333v682.666667H56.888889V284.444444z m56.888889 56.888889v568.888889h739.555555V341.333333H113.777778zM199.111111 170.666667L125.155556 284.444444H56.888889l113.777778-170.666666h625.777777l113.777778 170.666666h-68.266666l-73.955556-113.777777h-568.888889zM125.155556 284.444444H56.888889l113.777778-170.666666h625.777777l113.777778 170.666666h-68.266666l-73.955556-113.777777h-568.888889L125.155556 284.444444z" p-id="1514"/><path d="M227.555556 603.022222l39.822222-34.133333 221.866666 193.422222 216.177778-193.422222 39.822222 34.133333-256 227.555556z" p-id="1515"/><path d="M455.111111 398.222222h56.888889v369.777778H455.111111z" p-id="1516"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 48 48"><g fill="none" stroke="currentColor" stroke-linejoin="round" stroke-width="4"><path stroke-linecap="round" d="M41.4 11.551L36.333 5H11.667l-5.083 6.551"/><path d="M6 13a2 2 0 0 1 2-2h32a2 2 0 0 1 2 2v27a3 3 0 0 1-3 3H9a3 3 0 0 1-3-3V13Z"/><path stroke-linecap="round" d="m32 27l-8 8l-8-8m7.992-8v16"/></g></svg>

Before

Width:  |  Height:  |  Size: 1020 B

After

Width:  |  Height:  |  Size: 396 B

View File

@ -9,6 +9,7 @@
"common.tips": "Tips",
"common.open": "Open",
"common.input.placeholder": "Please input",
"common.success": "Operation successful",
"close.quit": "Quit",
"close.quit.cancel": "Cancel quit",
@ -81,6 +82,12 @@
"device.control.install.success": "Successfully installed {totalCount} apps to {deviceName}, {successCount} succeeded, {failCount} failed",
"device.control.install.success.single": "Successfully installed app to {deviceName}",
"device.control.install.error": "Install failed, please check app and try again",
"device.control.file.name": "File Manager",
"device.control.file.push": "Push File",
"device.control.file.push.placeholder": "Please select the file to push",
"device.control.file.push.success": "Successfully pushed {totalCount} files to {deviceName}, {successCount} succeeded, {failCount} failed",
"device.control.file.push.success.single": "Successfully pushed the file to {deviceName}",
"device.control.file.push.error": "Failed to push the file, please check the file and try again",
"device.control.capture": "Screenshot",
"device.control.capture.progress": "Capturing screenshot for {deviceName}...",
"device.control.capture.success.message": "Open screenshot location?",
@ -95,8 +102,10 @@
"device.control.switch": "Switch",
"device.control.gnirehtet": "Gnirehtet",
"device.control.gnirehtet.tips": "Gnirehtet provides reverse tethering for Android; Note: Initial connection requires authorization on the device.",
"device.control.gnirehtet.progress": "Starting Gnirehtet reverse tethering service...",
"device.control.gnirehtet.success": "Gnirehtet reverse tethering feature started successfully",
"device.control.gnirehtet.start": "Start Service",
"device.control.gnirehtet.start.success": "Gnirehtet reverse tethering feature started successfully",
"device.control.gnirehtet.stop": "Stop Service",
"device.control.gnirehtet.stop.success": "Service stopped successfully",
"device.control.mirror-group.name": "Mirror Group",
"device.control.mirror-group.tips": "When enabled, can mirror multiple simulated secondary displays and achieve multi-screen collaboration by operating each mirrored window. Note this requires ROM support and desktop mode enabled.",
"device.control.mirror-group.open": "Open {num} windows",

View File

@ -80,6 +80,12 @@
"device.control.install.success": "已成功将应用安装到 {deviceName} 中,共 {totalCount}个,成功 {successCount}个,失败 {failCount}个",
"device.control.install.success.single": "已成功将应用安装到 {deviceName} 中",
"device.control.install.error": "安装应用失败,请检查安装包后重试",
"device.control.file.name": "文件管理",
"device.control.file.push": "推送文件",
"device.control.file.push.placeholder": "请选择要推送的文件",
"device.control.file.push.success": "已成功将文件推送到 {deviceName} 中,共 {totalCount}个,成功 {successCount}个,失败 {failCount}个",
"device.control.file.push.success.single": "已成功将文件推送到 {deviceName} 中",
"device.control.file.push.error": "推送文件失败,请检查文件后重试",
"device.control.capture": "截取屏幕",
"device.control.capture.progress": "正在截取 {deviceName} 的屏幕快照...",
"device.control.capture.success.message": "是否前往截屏位置进行查看?",
@ -94,9 +100,8 @@
"device.control.switch": "切换键",
"device.control.gnirehtet": "反向供网",
"device.control.gnirehtet.tips": "使用 Gnirehtet 为 Android 提供反向网络共享;注意:首次连接需要在设备上进行授权",
"device.control.gnirehtet.progress": "正在启动 Gnirehtet 反向供网服务中...",
"device.control.gnirehtet.success": "Gnirehtet 反向网络共享功能启动成功",
"device.control.gnirehtet.start": "启动服务",
"device.control.gnirehtet.start.success": "Gnirehtet 反向网络共享功能启动成功",
"device.control.gnirehtet.stop": "停止服务",
"device.control.gnirehtet.stop.success": "停止服务成功",
"device.control.mirror-group.name": "多屏协同",