[#414] Added support for downloading Jellyfin items.

This commit is contained in:
Fabio Manganiello 2024-10-15 23:51:10 +02:00
parent e314a7bca9
commit 7620e1ead7
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774
5 changed files with 104 additions and 24 deletions

View file

@ -383,6 +383,8 @@ export default {
return await this.downloadTorrent(item, args) return await this.downloadTorrent(item, args)
case 'youtube': case 'youtube':
return await this.downloadYoutube(item, args) return await this.downloadYoutube(item, args)
case 'jellyfin':
return await this.downloadUrl(item.url)
} }
}, },

View file

@ -131,7 +131,7 @@
<div class="right side" v-text="computedItem.votes" /> <div class="right side" v-text="computedItem.votes" />
</div> </div>
<div class="row" v-if="computedItem?.genres"> <div class="row" v-if="computedItem?.genres?.length">
<div class="left side">Genres</div> <div class="left side">Genres</div>
<div class="right side" v-text="computedItem.genres.join(', ')" /> <div class="right side" v-text="computedItem.genres.join(', ')" />
</div> </div>
@ -190,7 +190,7 @@
<div class="right side" v-text="computedItem.peers" /> <div class="right side" v-text="computedItem.peers" />
</div> </div>
<div class="row" v-if="computedItem?.tags"> <div class="row" v-if="computedItem?.tags?.length">
<div class="left side">Tags</div> <div class="left side">Tags</div>
<div class="right side" v-text="computedItem.tags.join(', ')" /> <div class="right side" v-text="computedItem.tags.join(', ')" />
</div> </div>

View file

@ -28,24 +28,10 @@
<span class="actions"> <span class="actions">
<Dropdown title="Actions" icon-class="fa fa-ellipsis-h" ref="dropdown"> <Dropdown title="Actions" icon-class="fa fa-ellipsis-h" ref="dropdown">
<DropdownItem icon-class="fa fa-play" text="Play" @input="$emit('play')" <DropdownItem v-for="action in actions" :key="action.text"
v-if="item.type !== 'torrent' && item.item_type !== 'photo'" /> :icon-class="action.iconClass"
<DropdownItem icon-class="fa fa-play" text="Play (With Cache)" :text="action.text"
@input="$emit('play-with-opts', {item: item, opts: {cache: true}})" @input="action.action" />
v-if="item.type === 'youtube'" />
<DropdownItem icon-class="fa fa-eye" text="View" @input="showPhoto = true"
v-if="item.item_type === 'photo'" />
<DropdownItem icon-class="fa fa-download" text="Download" @input="$emit('download')"
v-if="(item.type === 'torrent' || item.type === 'youtube') && item.item_type !== 'channel' && item.item_type !== 'playlist'" />
<DropdownItem icon-class="fa fa-volume-high" text="Download Audio" @input="$emit('download-audio')"
v-if="item.type === 'youtube' && item.item_type !== 'channel' && item.item_type !== 'playlist'" />
<DropdownItem icon-class="fa fa-list" text="Add to playlist" @input="$emit('add-to-playlist')"
v-if="item.type === 'youtube'" />
<DropdownItem icon-class="fa fa-trash" text="Remove from playlist" @input="$emit('remove-from-playlist')"
v-if="item.type === 'youtube' && playlist?.length" />
<DropdownItem icon-class="fa fa-window-maximize" text="View in browser" @input="$emit('view')"
v-if="item.type === 'file'" />
<DropdownItem icon-class="fa fa-info-circle" text="Info" @input="$emit('select')" />
</Dropdown> </Dropdown>
</span> </span>
</div> </div>
@ -145,6 +131,88 @@ export default {
}, },
}, },
computed: {
actions() {
const actions = []
if (this.item.type !== 'torrent' && this.item.item_type !== 'photo') {
actions.push({
iconClass: 'fa fa-play',
text: 'Play',
action: () => this.$emit('play'),
})
}
if (this.item.type === 'youtube') {
actions.push({
iconClass: 'fa fa-play',
text: 'Play (With Cache)',
action: () => this.$emit('play-with-opts', {item: this.item, opts: {cache: true}}),
})
}
if (this.item.item_type === 'photo') {
actions.push({
iconClass: 'fa fa-eye',
text: 'View',
action: () => this.showPhoto = true,
})
}
if (this.item.type === 'file') {
actions.push({
iconClass: 'fa fa-window-maximize',
text: 'View in Browser',
action: () => this.$emit('view'),
})
}
if ((['torrent', 'youtube', 'jellyfin'].includes(this.item.type)) &&
this.item.item_type !== 'channel' &&
this.item.item_type !== 'playlist') {
actions.push({
iconClass: 'fa fa-download',
text: 'Download',
action: () => this.$emit('download'),
})
}
if (this.item.type === 'youtube' &&
this.item.item_type !== 'channel' &&
this.item.item_type !== 'playlist') {
actions.push({
iconClass: 'fa fa-volume-high',
text: 'Download Audio',
action: () => this.$emit('download-audio'),
})
}
if (this.item.type === 'youtube') {
actions.push({
iconClass: 'fa fa-list',
text: 'Add to Playlist',
action: () => this.$emit('add-to-playlist'),
})
}
if (this.item.type === 'youtube' && this.playlist?.length) {
actions.push({
iconClass: 'fa fa-trash',
text: 'Remove from Playlist',
action: () => this.$emit('remove-from-playlist'),
})
}
actions.push({
iconClass: 'fa fa-info-circle',
text: 'Info',
action: () => this.$emit('select'),
})
return actions
},
},
methods: { methods: {
onContextClick(e) { onContextClick(e) {
if (this.item?.item_type === 'photo') { if (this.item?.item_type === 'photo') {

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="media-jellyfin-container browser"> <div class="media-jellyfin-container browser">
<MediaNav :path="path" @back="$emit('back')" /> <MediaNav :path="path" @back="$emit('back')" @select="select" />
<div class="media-jellyfin-browser"> <div class="media-jellyfin-browser">
<Loading v-if="isLoading" /> <Loading v-if="isLoading" />
@ -41,10 +41,9 @@ export default {
'add-to-playlist', 'add-to-playlist',
'back', 'back',
'download', 'download',
'download-audio', 'path-change',
'play', 'play',
'play-with-opts', 'play-with-opts',
'select',
], ],
data() { data() {
@ -68,7 +67,6 @@ export default {
on: { on: {
'add-to-playlist': (item) => this.$emit('add-to-playlist', item), 'add-to-playlist': (item) => this.$emit('add-to-playlist', item),
'download': (item) => this.$emit('download', item), 'download': (item) => this.$emit('download', item),
'download-audio': (item) => this.$emit('download-audio', item),
'play': (item) => this.$emit('play', item), 'play': (item) => this.$emit('play', item),
'play-with-opts': (item) => this.$emit('play-with-opts', item), 'play-with-opts': (item) => this.$emit('play-with-opts', item),
}, },
@ -139,6 +137,8 @@ export default {
} else { } else {
this.path = [] this.path = []
} }
this.$emit('path-change', this.path)
}, },
selectCollection(collection) { selectCollection(collection) {

View file

@ -89,6 +89,16 @@ export default {
) )
.join('&') .join('&')
}, },
downloadUrl(url) {
const link = document.createElement('a')
link.href = url
link.download = ''
link.target = '_blank'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
},
}, },
} }
</script> </script>