Added video playlist support
This commit is contained in:
@@ -48,7 +48,9 @@
|
||||

|
||||
|
||||
### Playlists
|
||||
Waiting
|
||||

|
||||

|
||||
|
||||
# Have any questions?
|
||||
[Join our Matrix space](https://matrix.to/#/#ward:matrix.org)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import 'vidstack/bundle';
|
||||
|
||||
import { goto } from '$app/navigation';
|
||||
import { SponsorBlock, type Category } from 'sponsorblock-api';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { get } from 'svelte/store';
|
||||
@@ -15,13 +16,14 @@
|
||||
sponsorBlockCategories,
|
||||
sponsorBlockUrl
|
||||
} from '../store';
|
||||
import type { VideoPlay } from './Api/model';
|
||||
import type { PlaylistPageVideo, VideoPlay } from './Api/model';
|
||||
import { videoLength, type PhasedDescription } from './misc';
|
||||
import { getDynamicTheme } from './theme';
|
||||
|
||||
export let data: { video: VideoPlay; content: PhasedDescription };
|
||||
export let data: { video: VideoPlay; content: PhasedDescription; playlistId: string | null };
|
||||
export let currentTime: number = 0;
|
||||
export let audioMode = false;
|
||||
export let playlistVideos: PlaylistPageVideo[] | null = null;
|
||||
|
||||
let player: MediaPlayerElement;
|
||||
let src: PlayerSrc = [];
|
||||
@@ -36,6 +38,21 @@
|
||||
const proxyVideos = get(playerProxyVideos);
|
||||
|
||||
onMount(async () => {
|
||||
if (playlistVideos) {
|
||||
player.addEventListener('end', () => {
|
||||
if (!playlistVideos) return;
|
||||
|
||||
const playlistVideoIds = playlistVideos.map((value) => {
|
||||
return value.videoId;
|
||||
});
|
||||
|
||||
const currentVideoIndex = playlistVideoIds.indexOf(data.video.videoId);
|
||||
const newIndex = currentVideoIndex + 1;
|
||||
if (currentVideoIndex !== -1 && newIndex <= playlistVideoIds.length) {
|
||||
goto(`/watch/${playlistVideos[newIndex].videoId}?playlist=${data.playlistId}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!data.video.hlsUrl) {
|
||||
if (data.video.captions) {
|
||||
data.video.captions.forEach(async (caption) => {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { deleteUnsubscribe, getComments, postSubscribe } from '$lib/Api/index.js';
|
||||
import { deleteUnsubscribe, getComments, getPlaylist, postSubscribe } from '$lib/Api/index.js';
|
||||
import type { PlaylistPage, PlaylistPageVideo } from '$lib/Api/model.js';
|
||||
import Comment from '$lib/Comment.svelte';
|
||||
import PageLoading from '$lib/PageLoading.svelte';
|
||||
import Player from '$lib/Player.svelte';
|
||||
import Thumbnail from '$lib/Thumbnail.svelte';
|
||||
import { cleanNumber, numberWithCommas } from '$lib/misc.js';
|
||||
import { onMount } from 'svelte';
|
||||
import { get } from 'svelte/store';
|
||||
import { activePage, playerListenByDefault } from '../../../store.js';
|
||||
|
||||
@@ -14,6 +16,30 @@
|
||||
|
||||
activePage.set(null);
|
||||
|
||||
let playlistVideos: PlaylistPageVideo[] = [];
|
||||
let playlist: PlaylistPage | null = null;
|
||||
|
||||
onMount(async () => {
|
||||
if (!data.playlistId) return;
|
||||
|
||||
for (let page = 1; page < Infinity; page++) {
|
||||
console.log(page);
|
||||
const newPlaylist = await getPlaylist(data.playlistId, page);
|
||||
if (page === 1) {
|
||||
playlist = newPlaylist;
|
||||
}
|
||||
const newVideos = newPlaylist.videos;
|
||||
if (newVideos.length === 0) {
|
||||
break;
|
||||
}
|
||||
playlistVideos = [...playlistVideos, ...newVideos].sort(
|
||||
(a: PlaylistPageVideo, b: PlaylistPageVideo) => {
|
||||
return a.index < b.index ? -1 : 1;
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
async function loadMoreComments() {
|
||||
if (!comments) {
|
||||
return;
|
||||
@@ -47,7 +73,7 @@
|
||||
<div class="grid">
|
||||
<div class="s12 m12 l10">
|
||||
{#key data.video.videoId}
|
||||
<Player {data} {audioMode} bind:seekTo bind:currentTime />
|
||||
<Player {data} {audioMode} {playlistVideos} bind:seekTo bind:currentTime />
|
||||
{/key}
|
||||
|
||||
<h5>{data.video.title}</h5>
|
||||
@@ -180,12 +206,31 @@
|
||||
{/if}
|
||||
</div>
|
||||
<div class="s12 m12 l2">
|
||||
{#if data.video.recommendedVideos}
|
||||
{#each data.video.recommendedVideos as recommendedVideo}
|
||||
<article class="no-padding">
|
||||
<Thumbnail video={recommendedVideo} />
|
||||
</article>
|
||||
{/each}
|
||||
{#if !data.playlistId}
|
||||
{#if data.video.recommendedVideos}
|
||||
{#each data.video.recommendedVideos as recommendedVideo}
|
||||
<article class="no-padding">
|
||||
<Thumbnail video={recommendedVideo} />
|
||||
</article>
|
||||
{/each}
|
||||
{/if}
|
||||
{:else if playlist}
|
||||
<article style="height: 75vh;" class="scroll">
|
||||
<h6>{playlist.title}</h6>
|
||||
<p>{cleanNumber(playlist.viewCount)} views • {playlist.videoCount} videos</p>
|
||||
|
||||
<div class="divider"></div>
|
||||
<div class="space"></div>
|
||||
|
||||
{#each playlistVideos as playlistVideo}
|
||||
<article
|
||||
class="no-padding primary-border"
|
||||
class:border={playlistVideo.videoId === data.video.videoId}
|
||||
>
|
||||
<Thumbnail video={playlistVideo} playlistId={data.playlistId} />
|
||||
</article>
|
||||
{/each}
|
||||
</article>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@ import { error } from '@sveltejs/kit';
|
||||
import { get } from 'svelte/store';
|
||||
import { auth, playerProxyVideos, returnYtDislikes } from '../../../store';
|
||||
|
||||
export async function load({ params }) {
|
||||
export async function load({ params, url }) {
|
||||
let video;
|
||||
video = await getVideo(params.slug, get(playerProxyVideos));
|
||||
|
||||
@@ -39,6 +39,7 @@ export async function load({ params }) {
|
||||
returnYTDislikes: returnYTDislikes,
|
||||
comments: comments,
|
||||
subscribed: await amSubscribed(video.authorId),
|
||||
content: phaseDescription(video.description)
|
||||
content: phaseDescription(video.description),
|
||||
playlistId: url.searchParams.get('playlist')
|
||||
};
|
||||
};
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
Reference in New Issue
Block a user