[YouTube UI] Added support for browsing channels from search results.

This commit is contained in:
Fabio Manganiello 2024-07-13 00:04:26 +02:00
parent 5ff839919c
commit 55c4f5797b
Signed by untrusted user: blacklight
GPG key ID: D90FBA7F76362774
8 changed files with 90 additions and 16 deletions

View file

@ -24,6 +24,7 @@
:is="mediaProvider" :is="mediaProvider"
:filter="filter" :filter="filter"
:selected-playlist="selectedPlaylist" :selected-playlist="selectedPlaylist"
:selected-channel="selectedChannel"
@add-to-playlist="$emit('add-to-playlist', $event)" @add-to-playlist="$emit('add-to-playlist', $event)"
@back="back" @back="back"
@path-change="$emit('path-change', $event)" @path-change="$emit('path-change', $event)"
@ -68,6 +69,10 @@ export default {
selectedPlaylist: { selectedPlaylist: {
type: Object, type: Object,
}, },
selectedChannel: {
type: Object,
},
}, },
data() { data() {
@ -116,7 +121,7 @@ export default {
this.registerMediaProvider('YouTube') this.registerMediaProvider('YouTube')
}, },
async onPlaylistChange() { onPlaylistChange() {
if (!this.selectedPlaylist) if (!this.selectedPlaylist)
return return
@ -127,17 +132,34 @@ export default {
this.mediaProvider = this.mediaProviders[playlistMediaProvider] this.mediaProvider = this.mediaProviders[playlistMediaProvider]
} }
}, },
onChannelChange() {
if (!this.selectedChannel)
return
const channelType = this.selectedChannel.type?.toLowerCase()
const channelMediaProvider = this.mediaProvidersLookup[channelType]
if (channelMediaProvider) {
this.mediaProvider = this.mediaProviders[channelMediaProvider]
}
},
}, },
watch: { watch: {
selectedPlaylist() { selectedPlaylist() {
this.onPlaylistChange() this.onPlaylistChange()
}, },
selectedChannel() {
this.onChannelChange()
},
}, },
async mounted() { async mounted() {
await this.refreshMediaProviders() await this.refreshMediaProviders()
await this.onPlaylistChange() this.onPlaylistChange()
this.onChannelChange()
}, },
} }
</script> </script>

View file

@ -53,6 +53,7 @@
<Browser :filter="browserFilter" <Browser :filter="browserFilter"
:selected-playlist="selectedPlaylist" :selected-playlist="selectedPlaylist"
:selected-channel="selectedChannel"
@add-to-playlist="addToPlaylistItem = $event" @add-to-playlist="addToPlaylistItem = $event"
@back="selectedResult = null" @back="selectedResult = null"
@path-change="browserFilter = ''" @path-change="browserFilter = ''"
@ -208,6 +209,17 @@ export default {
return this.results[this.selectedResult] return this.results[this.selectedResult]
}, },
selectedChannel() {
if (this.selectedResult == null)
return null
const selectedItem = this.results[this.selectedResult]
if (selectedItem?.item_type !== 'channel')
return null
return this.results[this.selectedResult]
},
}, },
methods: { methods: {
@ -410,14 +422,14 @@ export default {
} }
const selectedItem = this.results[this.selectedResult] const selectedItem = this.results[this.selectedResult]
if (this.selectedResult != null && selectedItem?.item_type === 'playlist') { if (this.selectedResult != null && (selectedItem?.item_type === 'playlist' || selectedItem?.item_type === 'channel')) {
this.onPlaylistSelect() this.onBrowserItemSelect()
} else { } else {
this.selectedView = this.prevSelectedView || 'search' this.selectedView = this.prevSelectedView || 'search'
} }
}, },
onPlaylistSelect() { onBrowserItemSelect() {
if (this.prevSelectedView != this.selectedView) { if (this.prevSelectedView != this.selectedView) {
this.prevSelectedView = this.selectedView this.prevSelectedView = this.selectedView
} }

View file

@ -106,7 +106,7 @@ export default {
methods: { methods: {
play() { play() {
if (this.item.item_type === 'playlist') { if (this.item.item_type === 'playlist' || this.item.item_type === 'channel') {
this.select() this.select()
return return
} }

View file

@ -2,7 +2,7 @@
<div class="image-container" <div class="image-container"
:class="{ 'with-image': !!item?.image }"> :class="{ 'with-image': !!item?.image }">
<div class="play-overlay" @click="$emit('play', item)" v-if="hasPlay"> <div class="play-overlay" @click="$emit('play', item)" v-if="hasPlay">
<i class="fas fa-play" /> <i :class="overlayIconClass" />
</div> </div>
<span class="icon type-icon" v-if="typeIcons[item?.type]"> <span class="icon type-icon" v-if="typeIcons[item?.type]">
@ -16,7 +16,7 @@
<img class="image" :src="item.image" :alt="item.title" v-if="item?.image" /> <img class="image" :src="item.image" :alt="item.title" v-if="item?.image" />
<div class="image" v-else> <div class="image" v-else>
<div class="inner"> <div class="inner">
<i class="fas fa-play" /> <i :class="iconClass" />
</div> </div>
</div> </div>
@ -58,6 +58,33 @@ export default {
typeIcons: Icons, typeIcons: Icons,
} }
}, },
computed: {
iconClass() {
switch (this.item?.item_type) {
case 'channel':
return 'fas fa-user'
case 'playlist':
return 'fas fa-list'
case 'folder':
return 'fas fa-folder'
default:
return 'fas fa-play'
}
},
overlayIconClass() {
if (
this.item?.item_type === 'channel' ||
this.item?.item_type === 'playlist' ||
this.item?.item_type === 'folder'
) {
return 'fas fa-folder-open'
}
return 'fas fa-play'
},
},
} }
</script> </script>

View file

@ -23,6 +23,10 @@ export default {
selectedPlaylist: { selectedPlaylist: {
default: null, default: null,
}, },
selectedChannel: {
default: null,
},
}, },
data() { data() {

View file

@ -23,7 +23,7 @@
/> />
<Subscriptions :filter="filter" <Subscriptions :filter="filter"
:selected-channel="selectedChannel" :selected-channel="selectedChannel_"
@play="$emit('play', $event)" @play="$emit('play', $event)"
@select="onChannelSelected" @select="onChannelSelected"
v-else-if="selectedView === 'subscriptions'" v-else-if="selectedView === 'subscriptions'"
@ -63,7 +63,7 @@ export default {
youtubeConfig: null, youtubeConfig: null,
selectedView: null, selectedView: null,
selectedPlaylist_: null, selectedPlaylist_: null,
selectedChannel: null, selectedChannel_: null,
path: [], path: [],
} }
}, },
@ -126,7 +126,7 @@ export default {
if (view === 'playlists') if (view === 'playlists')
this.selectedPlaylist_ = null this.selectedPlaylist_ = null
else if (view === 'subscriptions') else if (view === 'subscriptions')
this.selectedChannel = null this.selectedChannel_ = null
if (view?.length) { if (view?.length) {
this.path = [ this.path = [
@ -152,7 +152,11 @@ export default {
}, },
onChannelSelected(channel) { onChannelSelected(channel) {
this.selectedChannel = channel.id this.selectedChannel_ = channel
if (!channel)
return
this.selectedView = 'subscriptions'
this.path.push({ this.path.push({
title: channel.name, title: channel.name,
}) })
@ -163,11 +167,16 @@ export default {
selectedPlaylist() { selectedPlaylist() {
this.onPlaylistSelected(this.selectedPlaylist) this.onPlaylistSelected(this.selectedPlaylist)
}, },
selectedChannel() {
this.onChannelSelected(this.selectedChannel)
},
}, },
mounted() { mounted() {
this.loadYoutubeConfig() this.loadYoutubeConfig()
this.onPlaylistSelected(this.selectedPlaylist) this.onPlaylistSelected(this.selectedPlaylist)
this.onChannelSelected(this.selectedChannel)
}, },
} }
</script> </script>

View file

@ -1,6 +1,6 @@
<template> <template>
<div class="media-youtube-subscriptions"> <div class="media-youtube-subscriptions">
<div class="subscriptions-index" v-if="!selectedChannel"> <div class="subscriptions-index" v-if="!selectedChannel?.id">
<Loading v-if="loading" /> <Loading v-if="loading" />
<NoItems :with-shadow="false" v-else-if="!channels?.length"> <NoItems :with-shadow="false" v-else-if="!channels?.length">
No channels found. No channels found.
@ -20,7 +20,7 @@
</div> </div>
<div class="subscription-body" v-else> <div class="subscription-body" v-else>
<Channel :id="selectedChannel" :filter="filter" @play="$emit('play', $event)" /> <Channel :id="selectedChannel.id" :filter="filter" @play="$emit('play', $event)" />
</div> </div>
</div> </div>
</template> </template>
@ -42,7 +42,7 @@ export default {
props: { props: {
selectedChannel: { selectedChannel: {
type: String, type: Object,
default: null, default: null,
}, },

View file

@ -118,7 +118,7 @@ export default {
mounted() { mounted() {
this.$watch('selectedResult', (value) => { this.$watch('selectedResult', (value) => {
if (value?.item_type === 'playlist') { if (value?.item_type === 'playlist' || value?.item_type === 'channel') {
this.$emit('select', null) this.$emit('select', null)
return return
} }