mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2024-10-22 10:46:28 +03:00
feat(export): Zip files when exporting several torrents (#1794)
This commit is contained in:
parent
1599b0f5e7
commit
7236b23281
3 changed files with 39 additions and 18 deletions
12
package-lock.json
generated
12
package-lock.json
generated
|
@ -16,6 +16,7 @@
|
|||
"@mdi/font": "^7.4.47",
|
||||
"@mdi/js": "^7.4.47",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"@zip.js/zip.js": "^2.7.45",
|
||||
"apexcharts": "^3.50.0",
|
||||
"axios": "^1.7.2",
|
||||
"dayjs": "^1.11.11",
|
||||
|
@ -1946,6 +1947,17 @@
|
|||
"resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
|
||||
"integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA=="
|
||||
},
|
||||
"node_modules/@zip.js/zip.js": {
|
||||
"version": "2.7.45",
|
||||
"resolved": "https://registry.npmjs.org/@zip.js/zip.js/-/zip.js-2.7.45.tgz",
|
||||
"integrity": "sha512-Mm2EXF33DJQ/3GWWEWeP1UCqzpQ5+fiMvT3QWspsXY05DyqqxWu7a9awSzU4/spHMHVFrTjani1PR0vprgZpow==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"bun": ">=0.7.0",
|
||||
"deno": ">=1.0.0",
|
||||
"node": ">=16.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
"@mdi/font": "^7.4.47",
|
||||
"@mdi/js": "^7.4.47",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"@zip.js/zip.js": "^2.7.45",
|
||||
"apexcharts": "^3.50.0",
|
||||
"axios": "^1.7.2",
|
||||
"dayjs": "^1.11.11",
|
||||
|
|
|
@ -7,6 +7,7 @@ import ShareLimitDialog from '@/components/Dialogs/ShareLimitDialog.vue'
|
|||
import SpeedLimitDialog from '@/components/Dialogs/SpeedLimitDialog.vue'
|
||||
import { useCategoryStore, useDashboardStore, useDialogStore, useMaindataStore, usePreferenceStore, useTagStore, useTorrentStore } from '@/stores'
|
||||
import { RightClickMenuEntryType } from '@/types/vuetorrent'
|
||||
import { BlobReader, BlobWriter, ZipWriter } from '@zip.js/zip.js'
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
@ -117,19 +118,26 @@ function setShareLimit() {
|
|||
dialogStore.createDialog(ShareLimitDialog, { hashes: hashes.value })
|
||||
}
|
||||
|
||||
function downloadFile(filename: string, blob: Blob) {
|
||||
const href = window.URL.createObjectURL(blob)
|
||||
const el = Object.assign(document.createElement('a'), { href, download: filename, style: { opacity: '0' } })
|
||||
document.body.appendChild(el)
|
||||
el.click()
|
||||
el.remove()
|
||||
}
|
||||
|
||||
async function exportTorrents() {
|
||||
hashes.value.forEach(hash => {
|
||||
torrentStore.exportTorrent(hash).then(blob => {
|
||||
const url = window.URL.createObjectURL(blob)
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.style.opacity = '0'
|
||||
link.setAttribute('download', `${hash}.torrent`)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
})
|
||||
})
|
||||
const ts = [...torrents.value]
|
||||
if (ts.length === 1) {
|
||||
const t = ts[0]!
|
||||
const blob = await torrentStore.exportTorrent(t.hash)
|
||||
downloadFile(`${t.name}.torrent`, blob)
|
||||
return
|
||||
}
|
||||
|
||||
const zipWriter = new ZipWriter(new BlobWriter('application/zip'), { bufferedWrite: true })
|
||||
await Promise.all(hashes.value.map(hash => torrentStore.exportTorrent(hash).then(blob => zipWriter.add(`${torrentStore.getTorrentByHash(hash)!.name}.torrent`, new BlobReader(blob)))))
|
||||
downloadFile('torrents.zip', await zipWriter.close())
|
||||
}
|
||||
|
||||
const menuData = computed<RightClickMenuEntryType[]>(() => [
|
||||
|
@ -216,12 +224,12 @@ const menuData = computed<RightClickMenuEntryType[]>(() => [
|
|||
children: [
|
||||
...(torrent.value?.tags.length
|
||||
? [
|
||||
{
|
||||
text: t('dashboard.right_click.tags.remove_all'),
|
||||
action: () => removeAllTags().then(maindataStore.forceMaindataSync),
|
||||
icon: 'mdi-playlist-remove'
|
||||
}
|
||||
]
|
||||
{
|
||||
text: t('dashboard.right_click.tags.remove_all'),
|
||||
action: () => removeAllTags().then(maindataStore.forceMaindataSync),
|
||||
icon: 'mdi-playlist-remove'
|
||||
}
|
||||
]
|
||||
: []),
|
||||
...tagStore.tags.map(tag => ({
|
||||
text: tag,
|
||||
|
|
Loading…
Reference in a new issue