Added playlist thumbnails

This commit is contained in:
WardPearce
2024-03-31 11:08:16 +13:00
parent 19166987d0
commit abc9836d66
8 changed files with 141 additions and 37 deletions
+2 -2
View File
@@ -1,6 +1,6 @@
import { get } from 'svelte/store';
import { auth, returnYTDislikesInstance } from '../../store';
import type { Channel, ChannelPage, Comments, ReturnYTDislikes, SearchSuggestion, Subscription, Video, VideoPlay } from './model';
import type { Channel, ChannelPage, Comments, Playlist, ReturnYTDislikes, SearchSuggestion, Subscription, Video, VideoPlay } from './model';
export function buildPath(path: string): string {
return `${import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE}/api/v1/${path}`;
@@ -65,7 +65,7 @@ export async function getSearch(search: string, options: {
sort_by?: "relevance" | "rating" | "upload_date" | "view_count",
type?: "video" | "playlist" | "channel" | "all";
page?: string;
}): Promise<(Channel | Video)[]> {
}): Promise<(Channel | Video | Playlist)[]> {
if (typeof options.sort_by === "undefined") {
options.sort_by = "relevance";
}
+19
View File
@@ -159,6 +159,25 @@ export interface Channel {
authorThumbnails: Image[];
}
export interface PlaylistVideo {
title: string;
videoId: string;
lengthSeconds: number;
videoThumbnails: Thumbnail[];
}
export interface Playlist {
type: "playlist";
title: string;
playlistId: string;
playlistThumbnail: string;
author: string;
authorId: string;
authorVerified: boolean;
videoCount: number;
videos: PlaylistVideo[];
}
export interface ChannelPage extends Channel {
allowedRegions: string[];
tabs: string[];
-24
View File
@@ -1,24 +0,0 @@
<script lang="ts">
import type { Channel } from './Api/model';
import { cleanNumber, truncate } from './misc';
export let channel: Channel;
</script>
<a href={`/channel/${channel.authorId}`}>
<div class="padding">
<div class="center-align">
<img
class="circle"
style="width: 90px;height: 90px;"
src={channel.authorThumbnails[0].url}
alt={channel.author}
/>
</div>
<h5 class="center-align">{truncate(channel.author, 14)}</h5>
<h6 style="margin-top: 0;" class="center-align grey-text medium-text">
{cleanNumber(channel.subCount)} subscribers
</h6>
<p>{channel.description}</p>
</div>
</a>
@@ -0,0 +1,44 @@
<script lang="ts">
import { onMount } from 'svelte';
import type { Channel } from './Api/model';
import { cleanNumber, truncate } from './misc';
export let channel: Channel;
let loading = true;
let loaded = false;
let failed = false;
let img: HTMLImageElement;
onMount(() => {
img = new Image();
img.src = channel.authorThumbnails[0].url;
img.onload = () => {
loaded = true;
loading = false;
};
img.onerror = () => {
loading = false;
failed = true;
};
});
</script>
<a href={`/channel/${channel.authorId}`} class="wave">
<div class="padding">
<div class="center-align">
{#if loading}
<progress class="circle"></progress>
{:else}
<img class="circle" style="width: 90px;height: 90px;" src={img.src} alt={channel.author} />
{/if}
</div>
<h5 class="center-align">{truncate(channel.author, 14)}</h5>
<h6 style="margin-top: 0;" class="center-align grey-text medium-text">
{cleanNumber(channel.subCount)} subscribers
</h6>
<p>{channel.description}</p>
</div>
</a>
@@ -0,0 +1,60 @@
<script lang="ts">
import { onMount } from 'svelte';
import type { Playlist } from './Api/model';
import { truncate } from './misc';
export let playlist: Playlist;
let loading = true;
let loaded = false;
let failed = false;
let img: HTMLImageElement;
onMount(() => {
img = new Image();
img.src = playlist.videos[0].videoThumbnails[4].url;
img.onload = () => {
loaded = true;
loading = false;
};
img.onerror = () => {
loading = false;
failed = true;
};
});
</script>
<a
href={`/playlist/${playlist.playlistId}`}
style="width: 100%; overflow: hidden;min-height:100px;"
class="wave"
>
{#if loading}
<progress class="circle"></progress>
{:else}
<img
class="responsive"
style="max-width: 100%;height: 100%;"
src={img.src}
alt="Thumbnail for playlist"
/>
{/if}
<div class="absolute right bottom small-margin black white-text small-text thumbnail-corner">
{playlist.videoCount} videos
</div>
</a>
<div class="small-padding">
<nav class="no-margin">
<div class="max">
<a href={`/playlist/${playlist.playlistId}`}
><div class="bold">{truncate(playlist.title)}</div></a
>
<div>
<a href={`/channel/${playlist.authorId}`}>{playlist.author}</a>
</div>
</div>
</nav>
</div>
+7 -8
View File
@@ -11,6 +11,8 @@
let loaded = false;
let failed = false;
let img: HTMLImageElement;
let progress: string | null;
if (get(playerSavePlaybackPosition)) {
progress = localStorage.getItem(`v_${video.videoId}`);
@@ -19,8 +21,8 @@
}
onMount(() => {
const img = new Image();
img.src = video.videoThumbnails[3].url;
img = new Image();
img.src = video.videoThumbnails[4].url;
img.onload = () => {
loaded = true;
@@ -44,7 +46,7 @@
<img
class="responsive"
style="max-width: 100%;height: 100%;"
src={video.videoThumbnails[4].url}
src={img.src}
alt="Thumbnail for video"
/>
{:else}
@@ -59,14 +61,11 @@
></progress>
{/if}
{#if !('liveVideo' in video) || !video.liveVideo}
<div class="absolute right bottom small-margin black white-text small-text">
<div class="absolute right bottom small-margin black white-text small-text thumbnail-corner">
&nbsp;{videoLength(video.lengthSeconds)}&nbsp;
</div>
{:else}
<div
class="absolute right bottom small-margin red white-text small-text"
style="padding: 0 1em;"
>
<div class="absolute right bottom small-margin red white-text small-text thumbnail-corner">
LIVE
</div>
{/if}
@@ -1,6 +1,7 @@
<script lang="ts">
import { getSearch } from '$lib/Api';
import Channel from '$lib/Channel.svelte';
import ChannelThumbnail from '$lib/ChannelThumbnail.svelte';
import PlaylistThumbnail from '$lib/PlaylistThumbnail.svelte';
import Thumbnail from '$lib/Thumbnail.svelte';
import { onDestroy, onMount } from 'svelte';
import { activePage } from '../../../store';
@@ -9,7 +10,7 @@
let currentPage = 1;
let search = data.search;
$: search = data.search;
activePage.set(null);
@@ -60,7 +61,9 @@
{#if item.type === 'video'}
<Thumbnail video={item} />
{:else if item.type === 'channel'}
<Channel channel={item} />
<ChannelThumbnail channel={item} />
{:else if item.type === 'playlist'}
<PlaylistThumbnail playlist={item} />
{/if}
</article>
</div>
+3
View File
@@ -0,0 +1,3 @@
.thumbnail-corner {
padding: .1em .4em;
}