[Media UI] Extend YouTube video events to all media views.

These events should be available for all YouTube videos, regardless of
where they are rendered:

- `add-to-playlist`
- `remove-from-playlist`
- `download`
This commit is contained in:
Fabio Manganiello 2024-07-15 22:32:13 +02:00
parent c416d0ea1f
commit e180c9c76f
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774
5 changed files with 83 additions and 30 deletions

View file

@ -17,6 +17,10 @@
v-if="item.type !== 'torrent'" /> v-if="item.type !== 'torrent'" />
<DropdownItem icon-class="fa fa-download" text="Download" @click="$emit('download')" <DropdownItem icon-class="fa fa-download" text="Download" @click="$emit('download')"
v-if="(item.type === 'torrent' || item.type === 'youtube') && item.item_type !== 'channel' && item.item_type !== 'playlist'" /> v-if="(item.type === 'torrent' || item.type === 'youtube') && item.item_type !== 'channel' && item.item_type !== 'playlist'" />
<DropdownItem icon-class="fa fa-list" text="Add to playlist" @click="$emit('add-to-playlist')"
v-if="item.type === 'youtube'" />
<DropdownItem icon-class="fa fa-trash" text="Remove from playlist" @click="$emit('remove-from-playlist')"
v-if="item.type === 'youtube' && playlist?.length" />
<DropdownItem icon-class="fa fa-window-maximize" text="View in browser" @click="$emit('view')" <DropdownItem icon-class="fa fa-window-maximize" text="View in browser" @click="$emit('view')"
v-if="item.type === 'file'" /> v-if="item.type === 'file'" />
<DropdownItem icon-class="fa fa-info-circle" text="Info" @click="$emit('select')" /> <DropdownItem icon-class="fa fa-info-circle" text="Info" @click="$emit('select')" />
@ -48,7 +52,15 @@ import Utils from "@/Utils";
export default { export default {
components: {Dropdown, DropdownItem, MediaImage}, components: {Dropdown, DropdownItem, MediaImage},
mixins: [Utils], mixins: [Utils],
emits: ['play', 'select', 'view', 'download'], emits: [
'add-to-playlist',
'download',
'play',
'remove-from-playlist',
'select',
'view',
],
props: { props: {
item: { item: {
type: Object, type: Object,
@ -64,6 +76,10 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
playlist: {
type: String,
},
}, },
data() { data() {

View file

@ -26,6 +26,8 @@
<Subscriptions :filter="filter" <Subscriptions :filter="filter"
:selected-channel="selectedChannel_" :selected-channel="selectedChannel_"
@add-to-playlist="$emit('add-to-playlist', $event)"
@download="$emit('download', $event)"
@play="$emit('play', $event)" @play="$emit('play', $event)"
@select="onChannelSelected" @select="onChannelSelected"
v-else-if="selectedView === 'subscriptions'" v-else-if="selectedView === 'subscriptions'"
@ -196,6 +198,7 @@ export default {
.body { .body {
height: calc(100% - $media-nav-height - 2px); height: calc(100% - $media-nav-height - 2px);
margin-top: 2px; margin-top: 2px;
overflow-y: auto;
} }
} }
</style> </style>

View file

@ -43,8 +43,10 @@
<Results :results="channel.items" <Results :results="channel.items"
:filter="filter" :filter="filter"
:result-index-step="null"
:selected-result="selectedResult" :selected-result="selectedResult"
ref="results" ref="results"
@add-to-playlist="$emit('add-to-playlist', $event)"
@download="$emit('download', $event)" @download="$emit('download', $event)"
@play="$emit('play', $event)" @play="$emit('play', $event)"
@scroll-end="loadNextPage" @scroll-end="loadNextPage"
@ -60,8 +62,13 @@ import Results from "@/components/panels/Media/Results";
import Utils from "@/Utils"; import Utils from "@/Utils";
export default { export default {
emits: ['download', 'play'],
mixins: [Utils], mixins: [Utils],
emits: [
'add-to-playlist',
'download',
'play',
],
components: { components: {
Loading, Loading,
Results, Results,
@ -102,26 +109,47 @@ export default {
async loadChannel() { async loadChannel() {
this.loading = true this.loading = true
try { try {
this.channel = await this.request('youtube.get_channel', {id: this.id}) await this.updateChannel(true)
this.subscribed = await this.request('youtube.is_subscribed', {channel_id: this.id}) this.subscribed = await this.request('youtube.is_subscribed', {channel_id: this.id})
} finally { } finally {
this.loading = false this.loading = false
} }
}, },
async updateChannel(init) {
const channel = await this.request(
'youtube.get_channel',
{id: this.id, next_page_token: this.channel?.next_page_token}
)
const itemsByUrl = this.itemsByUrl || {}
let items = channel.items
.filter(item => !itemsByUrl[item.url])
.map(item => {
return {
type: 'youtube',
...item,
}
})
if (!init) {
items = this.channel.items.concat(items)
}
this.channel = channel
this.channel.items = items
},
async loadNextPage() { async loadNextPage() {
if (!this.channel?.next_page_token || this.loadingNextPage) if (!this.channel?.next_page_token || this.loadingNextPage) {
return return
}
this.loadingNextPage = true
try { try {
const nextPage = await this.request( await this.timeout(500)
'youtube.get_channel', await this.updateChannel()
{id: this.id, next_page_token: this.channel.next_page_token}
)
this.channel.items.push(...nextPage.items.filter(item => !this.itemsByUrl[item.url]))
this.channel.next_page_token = nextPage.next_page_token
this.$refs.results.maxResultIndex += this.$refs.results.resultIndexStep
} finally { } finally {
this.loadingNextPage = false this.loadingNextPage = false
} }
@ -132,18 +160,6 @@ export default {
await this.request(`youtube.${action}`, {channel_id: this.id}) await this.request(`youtube.${action}`, {channel_id: this.id})
this.subscribed = !this.subscribed this.subscribed = !this.subscribed
}, },
onScroll(e) {
const el = e.target
if (!el)
return
const bottom = (el.scrollHeight - el.scrollTop) <= el.clientHeight + 100
if (!bottom)
return
this.loadNextPage()
},
}, },
mounted() { mounted() {

View file

@ -20,7 +20,13 @@
</div> </div>
<div class="subscription-body" v-else> <div class="subscription-body" v-else>
<Channel :id="selectedChannel.id" :filter="filter" @play="$emit('play', $event)" /> <Channel
:id="selectedChannel.id"
:filter="filter"
@add-to-playlist="$emit('add-to-playlist', $event)"
@download="$emit('download', $event)"
@play="$emit('play', $event)"
/>
</div> </div>
</div> </div>
</template> </template>
@ -32,8 +38,14 @@ import Loading from "@/components/Loading";
import Utils from "@/Utils"; import Utils from "@/Utils";
export default { export default {
emits: ['play', 'select'],
mixins: [Utils], mixins: [Utils],
emits: [
'add-to-playlist',
'download',
'play',
'select',
],
components: { components: {
Channel, Channel,
Loading, Loading,

View file

@ -90,14 +90,18 @@ export default {
computed: { computed: {
visibleResults() { visibleResults() {
return this.results let results = this.results
.filter((item) => { .filter((item) => {
if (!this.filter) if (!this.filter?.length)
return true return true
return item.title.toLowerCase().includes(this.filter.toLowerCase()) return item.title.toLowerCase().includes(this.filter.toLowerCase())
}) })
.slice(0, this.maxResultIndex)
if (this.maxResultIndex != null)
results = results.slice(0, this.maxResultIndex)
return results
}, },
}, },
@ -112,7 +116,9 @@ export default {
return return
this.$emit('scroll-end') this.$emit('scroll-end')
this.maxResultIndex += this.resultIndexStep
if (this.resultIndexStep != null)
this.maxResultIndex += this.resultIndexStep
}, },
}, },