mirror of
https://github.com/TeamPiped/Piped.git
synced 2024-12-24 22:43:35 +00:00
Merge pull request #960 from TeamPiped/playwith
Implement play with playlists.
This commit is contained in:
commit
128d39903d
@ -75,6 +75,7 @@ export default {
|
||||
},
|
||||
activated() {
|
||||
window.addEventListener("scroll", this.handleScroll);
|
||||
if (this.playlist) this.updateTitle();
|
||||
},
|
||||
deactivated() {
|
||||
window.removeEventListener("scroll", this.handleScroll);
|
||||
@ -86,7 +87,10 @@ export default {
|
||||
async getPlaylistData() {
|
||||
this.fetchPlaylist()
|
||||
.then(data => (this.playlist = data))
|
||||
.then(() => (document.title = this.playlist.name + " - Piped"));
|
||||
.then(() => this.updateTitle());
|
||||
},
|
||||
async updateTitle() {
|
||||
document.title = this.playlist.name + " - Piped";
|
||||
},
|
||||
handleScroll() {
|
||||
if (this.loading || !this.playlist || !this.playlist.nextpage) return;
|
||||
|
57
src/components/PlaylistVideos.vue
Normal file
57
src/components/PlaylistVideos.vue
Normal file
@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<div class="overflow-x-scroll h-screen-sm" ref="scrollable">
|
||||
<VideoItem
|
||||
v-for="(related, index) in playlist.relatedStreams"
|
||||
:key="related.url"
|
||||
:video="related"
|
||||
:index="index"
|
||||
:playlist-id="playlistId"
|
||||
height="94"
|
||||
width="168"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { nextTick } from "vue";
|
||||
import VideoItem from "./VideoItem.vue";
|
||||
export default {
|
||||
components: { VideoItem },
|
||||
props: {
|
||||
playlist: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
playlistId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
selectedIndex: {
|
||||
type: Number,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.updateScroll();
|
||||
},
|
||||
methods: {
|
||||
updateScroll() {
|
||||
const elems = Array.from(this.$refs.scrollable.children).filter(elm => elm.matches("div"));
|
||||
const index = this.selectedIndex - 1;
|
||||
if (index < elems.length)
|
||||
this.$refs.scrollable.scrollTop =
|
||||
elems[this.selectedIndex - 1].offsetTop - this.$refs.scrollable.offsetTop;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
playlist: {
|
||||
handler() {
|
||||
if (this.selectedIndex - 1 < this.playlist.relatedStreams.length)
|
||||
nextTick(() => {
|
||||
this.updateScroll();
|
||||
});
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
@ -1,6 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<router-link :to="video.url">
|
||||
<router-link
|
||||
:to="{
|
||||
path: '/watch',
|
||||
query: {
|
||||
v: video.url.substr(-11),
|
||||
...(playlistId && { list: playlistId }),
|
||||
...(index >= 0 && { index: index + 1 }),
|
||||
},
|
||||
}"
|
||||
>
|
||||
<img :height="height" :width="width" class="w-full" :src="video.thumbnail" alt="" loading="lazy" />
|
||||
<div class="relative text-sm">
|
||||
<span
|
||||
@ -26,7 +35,15 @@
|
||||
|
||||
<div class="float-right m-0 inline-block children:px-1">
|
||||
<router-link
|
||||
:to="video.url + '&listen=1'"
|
||||
:to="{
|
||||
path: '/watch',
|
||||
query: {
|
||||
v: video.url.substr(-11),
|
||||
...(playlistId && { list: playlistId }),
|
||||
...(index >= 0 && { index: index + 1 }),
|
||||
listen: '1',
|
||||
},
|
||||
}"
|
||||
:aria-label="'Listen to ' + video.title"
|
||||
:title="'Listen to ' + video.title"
|
||||
>
|
||||
|
@ -24,6 +24,14 @@ export default {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
playlist: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
index: {
|
||||
type: Number,
|
||||
default: -1,
|
||||
},
|
||||
sponsors: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
@ -38,6 +46,7 @@ export default {
|
||||
return {
|
||||
lastUpdate: new Date().getTime(),
|
||||
initialSeekComplete: false,
|
||||
destroying: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -171,9 +180,11 @@ export default {
|
||||
});
|
||||
},
|
||||
deactivated() {
|
||||
this.destroying = true;
|
||||
this.destroy(true);
|
||||
},
|
||||
unmounted() {
|
||||
this.destroying = true;
|
||||
this.destroy(true);
|
||||
},
|
||||
methods: {
|
||||
@ -281,6 +292,7 @@ export default {
|
||||
|
||||
if (noPrevPlayer)
|
||||
this.shakaPromise.then(() => {
|
||||
if (this.destroying) return;
|
||||
this.shaka.polyfill.installAll();
|
||||
|
||||
const localPlayer = new this.shaka.Player(videoEl);
|
||||
@ -355,13 +367,23 @@ export default {
|
||||
videoEl.addEventListener("ended", () => {
|
||||
if (!this.selectedAutoLoop && this.selectedAutoPlay && this.video.relatedStreams.length > 0) {
|
||||
const params = this.$route.query;
|
||||
let url = this.video.relatedStreams[0].url;
|
||||
let url = this.playlist?.relatedStreams?.[this.index]?.url ?? this.video.relatedStreams[0].url;
|
||||
const searchParams = new URLSearchParams();
|
||||
for (var param in params)
|
||||
switch (param) {
|
||||
case "v":
|
||||
case "t":
|
||||
break;
|
||||
case "index":
|
||||
if (this.index < this.playlist.relatedStreams.length)
|
||||
searchParams.set("index", this.index + 1);
|
||||
break;
|
||||
case "list":
|
||||
console.log(this.index);
|
||||
console.log(this.playlist.relatedStreams.length);
|
||||
if (this.index < this.playlist.relatedStreams.length)
|
||||
searchParams.set("list", params.list);
|
||||
break;
|
||||
default:
|
||||
searchParams.set(param, params[param]);
|
||||
break;
|
||||
|
@ -7,7 +7,7 @@ export default {
|
||||
activated() {
|
||||
const videoId = this.$route.params.videoId;
|
||||
if (videoId)
|
||||
this.$router.push({
|
||||
this.$router.replace({
|
||||
path: "/watch",
|
||||
query: { v: videoId },
|
||||
});
|
||||
|
@ -4,6 +4,8 @@
|
||||
ref="videoPlayer"
|
||||
:video="video"
|
||||
:sponsors="sponsors"
|
||||
:playlist="playlist"
|
||||
:index="index"
|
||||
:selected-auto-play="false"
|
||||
:selected-auto-loop="selectedAutoLoop"
|
||||
:is-embed="isEmbed"
|
||||
@ -18,6 +20,8 @@
|
||||
ref="videoPlayer"
|
||||
:video="video"
|
||||
:sponsors="sponsors"
|
||||
:playlist="playlist"
|
||||
:index="index"
|
||||
:selected-auto-play="selectedAutoPlay"
|
||||
:selected-auto-loop="selectedAutoLoop"
|
||||
/>
|
||||
@ -128,6 +132,12 @@
|
||||
</div>
|
||||
|
||||
<div v-if="video" class="order-first sm:order-last">
|
||||
<PlaylistVideos
|
||||
v-if="playlist"
|
||||
:playlist-id="playlistId"
|
||||
:playlist="playlist"
|
||||
:selected-index="index"
|
||||
/>
|
||||
<a
|
||||
class="btn mb-2 sm:hidden"
|
||||
@click="showRecs = !showRecs"
|
||||
@ -156,6 +166,7 @@ import ErrorHandler from "./ErrorHandler.vue";
|
||||
import CommentItem from "./CommentItem.vue";
|
||||
import Chapters from "./Chapters.vue";
|
||||
import PlaylistAddModal from "./PlaylistAddModal.vue";
|
||||
import PlaylistVideos from "./PlaylistVideos.vue";
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
@ -166,6 +177,7 @@ export default {
|
||||
CommentItem,
|
||||
Chapters,
|
||||
PlaylistAddModal,
|
||||
PlaylistVideos,
|
||||
},
|
||||
data() {
|
||||
const smallViewQuery = window.matchMedia("(max-width: 640px)");
|
||||
@ -173,6 +185,9 @@ export default {
|
||||
video: {
|
||||
title: "Loading...",
|
||||
},
|
||||
playlistId: null,
|
||||
playlist: null,
|
||||
index: null,
|
||||
sponsors: null,
|
||||
selectedAutoLoop: false,
|
||||
selectedAutoPlay: null,
|
||||
@ -237,6 +252,9 @@ export default {
|
||||
})();
|
||||
if (this.active) this.$refs.videoPlayer.loadVideo();
|
||||
});
|
||||
this.playlistId = this.$route.query.list;
|
||||
this.index = Number(this.$route.query.index);
|
||||
this.getPlaylistData();
|
||||
this.getSponsors();
|
||||
if (!this.isEmbed && this.getPreferenceBoolean("comments", true)) this.getComments();
|
||||
window.addEventListener("resize", () => {
|
||||
@ -307,6 +325,36 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
async getPlaylistData() {
|
||||
if (this.playlistId) {
|
||||
await this.fetchJson(this.apiUrl() + "/playlists/" + this.playlistId).then(data => {
|
||||
this.playlist = data;
|
||||
});
|
||||
await this.fetchPlaylistPages().then(() => {
|
||||
if (!(this.index >= 0)) {
|
||||
for (let i = 0; i < this.playlist.relatedStreams.length; i++)
|
||||
if (this.playlist.relatedStreams[i].url.substr(-11) == this.getVideoId()) {
|
||||
this.index = i + 1;
|
||||
this.$router.replace({
|
||||
query: { ...this.$route.query, index: this.index },
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
async fetchPlaylistPages() {
|
||||
if (this.playlist.nextpage) {
|
||||
await this.fetchJson(this.apiUrl() + "/nextpage/playlists/" + this.playlistId, {
|
||||
nextpage: this.playlist.nextpage,
|
||||
}).then(json => {
|
||||
this.playlist.relatedStreams = this.playlist.relatedStreams.concat(json.relatedStreams);
|
||||
this.playlist.nextpage = json.nextpage;
|
||||
});
|
||||
await this.fetchPlaylistPages();
|
||||
}
|
||||
},
|
||||
async getSponsors() {
|
||||
if (this.getPreferenceBoolean("sponsorblock", true))
|
||||
this.fetchSponsors().then(data => (this.sponsors = data));
|
||||
|
Loading…
Reference in New Issue
Block a user