From 705ba82fa1e6e6820f6f62a30821e76dfde6a8cb Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 25 Jun 2024 23:03:44 +0200 Subject: [PATCH 01/26] [Media UI] Added button to get the raw stream URL from youtube-dl compatible media. --- .../src/components/panels/Media/Index.vue | 5 +- .../src/components/panels/Media/Info.vue | 87 ++++++++++++++++++- .../src/components/panels/Media/Results.vue | 6 ++ 3 files changed, 92 insertions(+), 6 deletions(-) diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Index.vue b/platypush/backend/http/webapp/src/components/panels/Media/Index.vue index b6a59d36ea..311d3bb186 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Index.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Index.vue @@ -1,8 +1,6 @@ @@ -88,6 +100,7 @@ import Header from "@/components/panels/Media/Header"; import MediaUtils from "@/components/Media/Utils"; import MediaView from "@/components/Media/View"; import Nav from "@/components/panels/Media/Nav"; +import PlaylistAdder from "@/components/panels/Media/PlaylistAdder"; import Results from "@/components/panels/Media/Results"; import Subtitles from "@/components/panels/Media/Subtitles"; import Transfers from "@/components/panels/Torrent/Transfers"; @@ -102,6 +115,7 @@ export default { MediaView, Modal, Nav, + PlaylistAdder, Results, Subtitles, Transfers, @@ -139,6 +153,7 @@ export default { awaitingPlayTorrent: null, urlPlay: null, browserFilter: null, + addToPlaylistItem: null, torrentPlugin: null, torrentPlugins: [ 'torrent', @@ -487,4 +502,10 @@ export default { } } } + +:deep(.add-to-playlist-container) { + .body { + padding: 0 !important; + } +} diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Item.vue b/platypush/backend/http/webapp/src/components/panels/Media/Item.vue index 902f46caec..0ffceb3e60 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Item.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Item.vue @@ -4,6 +4,7 @@ :class="{selected: selected}" @click.right.prevent="$refs.dropdown.toggle()" v-if="!hidden"> +
@@ -19,6 +20,10 @@ v-if="item.type === 'torrent'" /> + + @@ -35,10 +40,15 @@ {{ formatDateTime(item.created_at, true) }} + + + Are you sure you want to remove this item from the playlist? + + + diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/Mixin.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/Mixin.vue index 8de115bc2a..4d01819010 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/Mixin.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/Mixin.vue @@ -2,8 +2,18 @@ import Utils from "@/Utils"; export default { - emits: ['back', 'path-change', 'play'], mixins: [Utils], + emits: [ + 'add-to-playlist', + 'back', + 'create-playlist', + 'path-change', + 'play', + 'remove-from-playlist', + 'remove-playlist', + 'rename-playlist', + ], + props: { filter: { type: String, diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue index c6491590d3..f2907cec4c 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue @@ -8,17 +8,27 @@
+ @add-to-playlist="$emit('add-to-playlist', $event)" + @play="$emit('play', $event)" + v-if="selectedView === 'feed'" + /> + + v-else-if="selectedView === 'playlists'" + /> + + v-else-if="selectedView === 'subscriptions'" + /> +
@@ -87,6 +97,21 @@ export default { } }, + async removeFromPlaylist(event) { + const playlistId = event.playlist_id + const videoId = event.item.url + this.loading = true + + try { + await this.request('youtube.remove_from_playlist', { + playlist_id: playlistId, + video_id: videoId, + }) + } finally { + this.loading = false + } + }, + selectView(view) { this.selectedView = view if (view === 'playlists') diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Feed.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Feed.vue index eaadfda6ca..58793c622e 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Feed.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Feed.vue @@ -9,6 +9,7 @@ :filter="filter" :sources="{'youtube': true}" :selected-result="selectedResult" + @add-to-playlist="$emit('add-to-playlist', $event)" @select="selectedResult = $event" @play="$emit('play', $event)" v-else /> @@ -22,8 +23,12 @@ import Results from "@/components/panels/Media/Results"; import Utils from "@/Utils"; export default { - emits: ['play'], mixins: [Utils], + emits: [ + 'add-to-playlist', + 'play', + ], + components: { Loading, NoItems, diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue index c09d0089af..4a70e42e0d 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue @@ -8,9 +8,12 @@ @@ -22,8 +25,13 @@ import Results from "@/components/panels/Media/Results"; import Utils from "@/Utils"; export default { - emits: ['play'], mixins: [Utils], + emits: [ + 'add-to-playlist', + 'play', + 'remove-from-playlist', + ], + components: { Loading, NoItems, diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue index 823e11145e..fae4433bfc 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue @@ -18,7 +18,14 @@
- +
@@ -31,8 +38,17 @@ import Playlist from "./Playlist"; import Utils from "@/Utils"; export default { - emits: ['play', 'select'], mixins: [Utils], + emits: [ + 'add-to-playlist', + 'create-playlist', + 'play', + 'remove-from-playlist', + 'remove-playlist', + 'rename-playlist', + 'select', + ], + components: { Loading, MediaImage, diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Results.vue b/platypush/backend/http/webapp/src/components/panels/Media/Results.vue index 62f14722b4..5d4292f46c 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Results.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Results.vue @@ -4,9 +4,12 @@
Date: Thu, 27 Jun 2024 01:26:00 +0200 Subject: [PATCH 04/26] [Youtube UI] More playlist actions. - `create_playlist` - `rename_playlist` - `delete_playlist` --- .../src/components/elements/ConfirmDialog.vue | 5 +- .../components/elements/FloatingButton.vue | 2 +- .../src/components/elements/TextPrompt.vue | 7 +- .../panels/Media/Providers/YouTube.vue | 9 + .../Media/Providers/YouTube/Playlists.vue | 210 ++++++++++++++++++ 5 files changed, 229 insertions(+), 4 deletions(-) diff --git a/platypush/backend/http/webapp/src/components/elements/ConfirmDialog.vue b/platypush/backend/http/webapp/src/components/elements/ConfirmDialog.vue index ad93299854..19ebf3b74e 100644 --- a/platypush/backend/http/webapp/src/components/elements/ConfirmDialog.vue +++ b/platypush/backend/http/webapp/src/components/elements/ConfirmDialog.vue @@ -1,5 +1,5 @@ From 910304b817d8c9f664efb4a5a280365e1c8e4ba7 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Mon, 15 Jul 2024 23:12:04 +0200 Subject: [PATCH 20/26] [Media UI] More URI-persisted navigation items. - `player` - `provider` --- .../src/components/panels/Media/Browser.vue | 43 +++++++++++++++++-- .../src/components/panels/Media/Index.vue | 26 ++++++++--- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Browser.vue b/platypush/backend/http/webapp/src/components/panels/Media/Browser.vue index b7cdf03f7f..adecd59797 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Browser.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Browser.vue @@ -37,7 +37,7 @@ diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Index.vue b/platypush/backend/http/webapp/src/components/panels/Media/Index.vue index 2da54f7cb3..8b7f8936e0 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Index.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Index.vue @@ -556,6 +556,14 @@ export default { if (args.view) { this.selectedView = args.view } + + if (args.player && this.players?.length) { + this.selectedPlayer = this.players.find((player) => player.name === args.player) + } + + if (args.subtitles) { + this.selectedSubtitles = args.subtitles + } }, onDownloadStarted(event) { @@ -637,21 +645,29 @@ export default { }, }, - async mounted() { - this.$watch(() => this.selectedPlayer, (player) => { + watch: { + selectedPlayer(player) { + this.setUrlArgs({player: player?.name}) if (player) this.refresh() - }) + }, - this.$watch(() => this.selectedSubtitles, (subs) => { + selectedSubtitles(subs) { + this.setUrlArgs({subtitles: this.selectedSubtitles}) if (new Set(['play', 'pause']).has(this.selectedPlayer?.status?.state)) { if (subs) this.selectedPlayer.component.addSubtitles(subs) else this.selectedPlayer.component.removeSubtitles() } - }) + }, + selectedView() { + this.setUrlArgs({view: this.selectedView}) + }, + }, + + async mounted() { this.torrentPlugin = this.getTorrentPlugin() this.subscribe(this.onTorrentQueued,'on-torrent-queued', 'platypush.message.event.torrent.TorrentQueuedEvent') From c5ac02d133b54e163dc374583ffdf06e1727ed4d Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 16 Jul 2024 01:18:33 +0200 Subject: [PATCH 21/26] [Media UI] Misc style improvements. --- .../src/components/panels/Media/Item.vue | 2 ++ .../components/panels/Media/Providers/Nav.vue | 3 +++ .../Media/Providers/YouTube/header.scss | 21 ++++++++++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Item.vue b/platypush/backend/http/webapp/src/components/panels/Media/Item.vue index d47f4da4c4..440ca47dad 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Item.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Item.vue @@ -97,6 +97,8 @@ export default { display: flex; flex-direction: column; align-items: center; + max-height: 23.5em; + height: 100%; cursor: initial !important; margin-bottom: 5px; border: 1px solid transparent; diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/Nav.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/Nav.vue index b475082f91..96f760e13d 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/Nav.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/Nav.vue @@ -48,6 +48,9 @@ export default { @import "../style.scss"; .nav { + overflow-x: auto !important; + overflow-y: hidden !important; + .path .token .icon { margin-right: 0.5em; } diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/header.scss b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/header.scss index c8d8dd8070..b564d9af74 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/header.scss +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/header.scss @@ -1,7 +1,19 @@ -$banner-height: 100px; +$banner-height: var(--banner-height); $info-bg: rgba(0, 0, 0, 0.5); $info-fg: rgba(255, 255, 255, 0.9); +@include until($tablet) { + .playlist-container, .channel { + --banner-height: 5em; + } +} + +@include from($tablet) { + .playlist-container, .channel { + --banner-height: 100px; + } +} + .header { border-bottom: $default-border-2; margin-bottom: 0.5em; @@ -86,7 +98,14 @@ $info-fg: rgba(255, 255, 255, 0.9); } } + .title-container { + max-height: var(--banner-height); + overflow-y: hidden; + } + .title { + height: 100%; + align-content: center; color: $default-fg-2; font-size: 1.7em; font-weight: bold; From c95381cead6e7fbaa768f59204aacd40b8a351a5 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 16 Jul 2024 01:19:29 +0200 Subject: [PATCH 22/26] [Media UI] Added more permalinks. - `channel` - `playlist` --- .../panels/Media/Providers/YouTube.vue | 29 +++++++++++++++++++ .../Media/Providers/YouTube/Channel.vue | 11 +++++-- .../Media/Providers/YouTube/Playlist.vue | 5 ++++ .../Media/Providers/YouTube/Playlists.vue | 18 ++++++++++-- .../Media/Providers/YouTube/Subscriptions.vue | 12 ++++++-- 5 files changed, 68 insertions(+), 7 deletions(-) diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue index 811dd5acda..2b93749d74 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue @@ -165,6 +165,16 @@ export default { title: channel.name, }) }, + + initView() { + const args = this.getUrlArgs() + + if (args.section) + this.selectedView = args.section + + if (this.selectedView) + this.selectView(this.selectedView) + }, }, watch: { @@ -172,16 +182,35 @@ export default { this.onPlaylistSelected(this.selectedPlaylist) }, + selectedPlaylist_(value) { + if (value == null) + this.setUrlArgs({playlist: null}) + }, + selectedChannel() { this.onChannelSelected(this.selectedChannel) }, + + selectedChannel_(value) { + if (value == null) + this.setUrlArgs({channel: null}) + }, + + selectedView() { + this.setUrlArgs({section: this.selectedView}) + }, }, mounted() { this.loadYoutubeConfig() + this.initView() this.onPlaylistSelected(this.selectedPlaylist) this.onChannelSelected(this.selectedChannel) }, + + unmounted() { + this.setUrlArgs({section: null}) + }, } diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Channel.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Channel.vue index 6078c759dd..5127484254 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Channel.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Channel.vue @@ -162,8 +162,13 @@ export default { }, }, - mounted() { - this.loadChannel() + async mounted() { + this.setUrlArgs({channel: this.id}) + await this.loadChannel() + }, + + unmounted() { + this.setUrlArgs({channel: null}) }, } @@ -187,7 +192,7 @@ export default { .actions { display: flex; flex-direction: column; - align-items: center; + align-items: flex-end; button { background: $default-bg-7; diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue index c48ca6fa7f..96c52e632f 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue @@ -132,8 +132,13 @@ export default { }, mounted() { + this.setUrlArgs({playlist: this.id}) this.loadItems() }, + + unmounted() { + this.setUrlArgs({playlist: null}) + }, } diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue index f1943aa982..6900f98e65 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue @@ -234,8 +234,22 @@ export default { }, }, - mounted() { - this.loadPlaylists() + async mounted() { + await this.loadPlaylists() + + const args = this.getUrlArgs() + if (args.playlist) { + const playlist = this.playlistsById[args.playlist] + if (playlist) { + this.$emit('select', playlist) + } else { + this.$emit('select', {id: args.playlist}) + } + } + }, + + unmouted() { + this.setUrlArgs({section: null}) }, } diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Subscriptions.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Subscriptions.vue index 57b7e8b481..a1ff46ed10 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Subscriptions.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Subscriptions.vue @@ -91,10 +91,18 @@ export default { this.loading = false } }, + + initView() { + const args = this.getUrlArgs() + if (args.channel) { + this.$emit('select', {id: args.channel}) + } + }, }, - mounted() { - this.loadSubscriptions() + async mounted() { + await this.loadSubscriptions() + this.initView() }, } From e710a3a974203a3ee4aa2a4aa455d963ba4d1507 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 16 Jul 2024 02:30:47 +0200 Subject: [PATCH 23/26] [Media UI] Support for `open-channel` events from any media item. --- .../src/components/panels/Media/Index.vue | 21 +++++++++++++++++++ .../src/components/panels/Media/Item.vue | 3 ++- .../panels/Media/Providers/YouTube.vue | 17 +++++++++++++++ .../Media/Providers/YouTube/Channel.vue | 2 ++ .../panels/Media/Providers/YouTube/Feed.vue | 2 ++ .../Media/Providers/YouTube/Playlist.vue | 2 ++ .../Media/Providers/YouTube/Playlists.vue | 2 ++ .../src/components/panels/Media/Results.vue | 2 ++ 8 files changed, 50 insertions(+), 1 deletion(-) diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Index.vue b/platypush/backend/http/webapp/src/components/panels/Media/Index.vue index 8b7f8936e0..3a4a844849 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Index.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Index.vue @@ -55,6 +55,7 @@ :loading="loading" :filter="browserFilter" @add-to-playlist="addToPlaylistItem = $event" + @open-channel="selectChannelFromItem" @select="onResultSelect($event)" @play="play" @view="view" @@ -643,6 +644,26 @@ export default { if (event.path in this.downloads) delete this.downloads[event.path] }, + + selectChannelFromItem(item) { + const mediaProvider = item?.type + const channelId = ( + item?.channel_id || + item?.channel?.id || + item?.channel_url.split('/').pop() + ) + + if (!mediaProvider && channelId == null) + return + + this.setUrlArgs({ + provider: mediaProvider, + section: 'subscriptions', + channel: channelId, + }) + + this.selectedView = 'browser' + }, }, watch: { diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Item.vue b/platypush/backend/http/webapp/src/components/panels/Media/Item.vue index 440ca47dad..a313186b46 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Item.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Item.vue @@ -29,7 +29,7 @@
- + @@ -55,6 +55,7 @@ export default { emits: [ 'add-to-playlist', 'download', + 'open-channel', 'play', 'remove-from-playlist', 'select', diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue index 2b93749d74..296afee3fc 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube.vue @@ -10,6 +10,7 @@ @@ -18,6 +19,7 @@ :selected-playlist="selectedPlaylist_" @add-to-playlist="$emit('add-to-playlist', $event)" @download="$emit('download', $event)" + @open-channel="selectChannelFromItem" @play="$emit('play', $event)" @remove-from-playlist="removeFromPlaylist" @select="onPlaylistSelected" @@ -175,6 +177,21 @@ export default { if (this.selectedView) this.selectView(this.selectedView) }, + + async selectChannelFromItem(item) { + if (!item.channel_url) + return + + const channel = await this.request( + 'youtube.get_channel', + {id: item.channel_url.split('/').pop()} + ) + + if (!channel) + return + + this.onChannelSelected(channel) + }, }, watch: { diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Channel.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Channel.vue index 5127484254..22d57ade8b 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Channel.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Channel.vue @@ -48,6 +48,7 @@ ref="results" @add-to-playlist="$emit('add-to-playlist', $event)" @download="$emit('download', $event)" + @open-channel="$emit('open-channel', $event)" @play="$emit('play', $event)" @scroll-end="loadNextPage" @select="selectedResult = $event" @@ -66,6 +67,7 @@ export default { emits: [ 'add-to-playlist', 'download', + 'open-channel', 'play', ], diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Feed.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Feed.vue index d8bb5ee2e1..681401cab8 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Feed.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Feed.vue @@ -11,6 +11,7 @@ :selected-result="selectedResult" @add-to-playlist="$emit('add-to-playlist', $event)" @download="$emit('download', $event)" + @open-channel="$emit('open-channel', $event)" @select="selectedResult = $event" @play="$emit('play', $event)" v-else /> @@ -28,6 +29,7 @@ export default { emits: [ 'add-to-playlist', 'download', + 'open-channel', 'play', ], diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue index 96c52e632f..aed7e75019 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlist.vue @@ -51,6 +51,7 @@ :selected-result="selectedResult" @add-to-playlist="$emit('add-to-playlist', $event)" @download="$emit('download', $event)" + @open-channel="$emit('open-channel', $event)" @play="$emit('play', $event)" @remove-from-playlist="$emit('remove-from-playlist', $event)" @select="selectedResult = $event" @@ -70,6 +71,7 @@ export default { emits: [ 'add-to-playlist', 'download', + 'open-channel', 'play', 'remove-from-playlist', ], diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue index 6900f98e65..17fe0bedf5 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Providers/YouTube/Playlists.vue @@ -32,6 +32,7 @@ :metadata="playlistsById[selectedPlaylist.id] || selectedPlaylist" @add-to-playlist="$emit('add-to-playlist', $event)" @download="$emit('download', $event)" + @open-channel="$emit('open-channel', $event)" @remove-from-playlist="$emit('remove-from-playlist', {item: $event, playlist_id: selectedPlaylist.id})" @play="$emit('play', $event)" /> @@ -112,6 +113,7 @@ export default { 'add-to-playlist', 'create-playlist', 'download', + 'open-channel', 'play', 'remove-from-playlist', 'remove-playlist', diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Results.vue b/platypush/backend/http/webapp/src/components/panels/Media/Results.vue index 9ad160a074..c6a41c39d6 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Results.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Results.vue @@ -9,6 +9,7 @@ :playlist="playlist" :selected="selectedResult === i" @add-to-playlist="$emit('add-to-playlist', item)" + @open-channel="$emit('open-channel', item)" @remove-from-playlist="$emit('remove-from-playlist', item)" @select="$emit('select', i)" @play="$emit('play', item)" @@ -36,6 +37,7 @@ export default { emits: [ 'add-to-playlist', 'download', + 'open-channel', 'play', 'remove-from-playlist', 'scroll-end', From aa92db985060451198239d297503bbaa0b318e09 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 16 Jul 2024 03:10:54 +0200 Subject: [PATCH 24/26] [UI] A more robust way to encode/decode URI arguments. --- .../backend/http/webapp/src/utils/Url.vue | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/platypush/backend/http/webapp/src/utils/Url.vue b/platypush/backend/http/webapp/src/utils/Url.vue index 4a7e17d9e3..6bd00db4ac 100644 --- a/platypush/backend/http/webapp/src/utils/Url.vue +++ b/platypush/backend/http/webapp/src/utils/Url.vue @@ -16,7 +16,7 @@ export default { .reduce((acc, obj) => { const tokens = obj.split('=') if (tokens[0]?.length) - acc[tokens[0]] = tokens[1] + acc[tokens[0]] = decodeURIComponent(tokens[1]) return acc }, {}) }, @@ -40,10 +40,24 @@ export default { window.location.href = location }, + encodeValue(value) { + if (!value?.length || value === 'null' || value === 'undefined') + return '' + + // Don't re-encode the value if it's already encoded + if (value.match(/%[0-9A-F]{2}/i)) + return value + + return encodeURIComponent(value) + }, + fragmentFromArgs(args) { return Object.entries(args) + .filter( + ([key, value]) => this.encodeValue(key)?.length && this.encodeValue(value)?.length + ) .map( - ([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}` + ([key, value]) => `${this.encodeValue(key)}=${this.encodeValue(value)}` ) .join('&') }, From 5ebdb381f12a8a680ec674f016aa7f0847797fc2 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 16 Jul 2024 03:12:18 +0200 Subject: [PATCH 25/26] [File UI] Persist the path on the URI. --- .../backend/http/webapp/src/components/File/Browser.vue | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/platypush/backend/http/webapp/src/components/File/Browser.vue b/platypush/backend/http/webapp/src/components/File/Browser.vue index dc41e1db39..4e7eabb1ca 100644 --- a/platypush/backend/http/webapp/src/components/File/Browser.vue +++ b/platypush/backend/http/webapp/src/components/File/Browser.vue @@ -134,6 +134,7 @@ export default { try { this.files = await this.request('file.list', {path: this.path}) this.$emit('path-change', this.path) + this.setUrlArgs({path: decodeURIComponent(this.path)}) } finally { this.loading = false } @@ -165,8 +166,16 @@ export default { }, mounted() { + const args = this.getUrlArgs() + if (args.path) + this.path = args.path + this.refresh() }, + + unmounted() { + this.setUrlArgs({path: null}) + }, } From b44bd0be32782773a4559311a5fa393bff032dc9 Mon Sep 17 00:00:00 2001 From: Fabio Manganiello Date: Tue, 16 Jul 2024 03:48:45 +0200 Subject: [PATCH 26/26] [Media UI] Download Audio support. --- .../src/components/panels/Media/Browser.vue | 2 ++ .../src/components/panels/Media/Index.vue | 25 +++++++++++++------ .../src/components/panels/Media/Item.vue | 3 +++ .../panels/Media/Providers/Mixin.vue | 1 + .../panels/Media/Providers/YouTube.vue | 3 +++ .../Media/Providers/YouTube/Channel.vue | 2 ++ .../panels/Media/Providers/YouTube/Feed.vue | 2 ++ .../Media/Providers/YouTube/Playlist.vue | 2 ++ .../Media/Providers/YouTube/Playlists.vue | 2 ++ .../Media/Providers/YouTube/Subscriptions.vue | 2 ++ .../src/components/panels/Media/Results.vue | 5 +++- 11 files changed, 40 insertions(+), 9 deletions(-) diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Browser.vue b/platypush/backend/http/webapp/src/components/panels/Media/Browser.vue index adecd59797..b224ed6b4d 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Browser.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Browser.vue @@ -28,6 +28,7 @@ @add-to-playlist="$emit('add-to-playlist', $event)" @back="back" @download="$emit('download', $event)" + @download-audio="$emit('download-audio', $event)" @path-change="$emit('path-change', $event)" @play="$emit('play', $event)" /> @@ -50,6 +51,7 @@ export default { 'back', 'create-playlist', 'download', + 'download-audio', 'path-change', 'play', 'remove-from-playlist', diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Index.vue b/platypush/backend/http/webapp/src/components/panels/Media/Index.vue index 3a4a844849..3e1798bc7d 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Index.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Index.vue @@ -60,6 +60,7 @@ @play="play" @view="view" @download="download" + @download-audio="downloadAudio" v-if="selectedView === 'search'" /> @@ -82,6 +83,7 @@ @add-to-playlist="addToPlaylistItem = $event" @back="selectedResult = null" @download="download" + @download-audio="downloadAudio" @path-change="browserFilter = ''" @play="play($event)" v-else-if="selectedView === 'browser'" @@ -344,15 +346,19 @@ export default { window.open(ret.url, '_blank') }, - async download(item) { + async download(item, args) { switch (item.type) { case 'torrent': - return await this.downloadTorrent(item) + return await this.downloadTorrent(item, args) case 'youtube': - return await this.downloadYoutube(item) + return await this.downloadYoutube(item, args) } }, + async downloadAudio(item) { + await this.download(item, {onlyAudio: true}) + }, + async refresh() { this.selectedPlayer.status = await this.selectedPlayer.component.status(this.selectedPlayer) }, @@ -454,7 +460,7 @@ export default { return await this.request(`${torrentPlugin}.download`, {torrent: item.url || item}) }, - async downloadYoutube(item) { + async downloadYoutube(item, args) { if (!item?.url) { this.notify({ text: 'No YouTube URL available', @@ -464,10 +470,13 @@ export default { return } - await this.request( - `${this.pluginName}.download`, - {url: item.url}, - ) + const requestArgs = {url: item.url} + const onlyAudio = !!args?.onlyAudio + if (onlyAudio) { + requestArgs.only_audio = true + } + + await this.request(`${this.pluginName}.download`, requestArgs) }, async selectSubtitles(item) { diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Item.vue b/platypush/backend/http/webapp/src/components/panels/Media/Item.vue index a313186b46..278956d2fd 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Item.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Item.vue @@ -17,6 +17,8 @@ v-if="item.type !== 'torrent'" /> +
@@ -42,6 +43,7 @@ export default { emits: [ 'add-to-playlist', 'download', + 'download-audio', 'play', 'select', ], diff --git a/platypush/backend/http/webapp/src/components/panels/Media/Results.vue b/platypush/backend/http/webapp/src/components/panels/Media/Results.vue index c6a41c39d6..6c602fd9e2 100644 --- a/platypush/backend/http/webapp/src/components/panels/Media/Results.vue +++ b/platypush/backend/http/webapp/src/components/panels/Media/Results.vue @@ -14,7 +14,9 @@ @select="$emit('select', i)" @play="$emit('play', item)" @view="$emit('view', item)" - @download="$emit('download', item)" /> + @download="$emit('download', item)" + @download-audio="$emit('download-audio', item)" + /> @@ -37,6 +39,7 @@ export default { emits: [ 'add-to-playlist', 'download', + 'download-audio', 'open-channel', 'play', 'remove-from-playlist',