Started channel page
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { get } from 'svelte/store';
|
||||
import { invidiousInstance, returnYTDislikesInstance } from '../../store';
|
||||
import type { Comments, ReturnYTDislikes, Video, VideoPlay } from './model';
|
||||
import type { Channel, Comments, ReturnYTDislikes, Video, VideoPlay } from './model';
|
||||
|
||||
export function buildPath(path: string): string {
|
||||
return `${get(invidiousInstance)}/api/v1/${path}`;
|
||||
@@ -26,4 +26,9 @@ export async function getComments(videoId: string, parameters: { sortBy: "top" |
|
||||
path.search = new URLSearchParams(parameters).toString();
|
||||
const resp = await fetch(path);
|
||||
return await resp.json();
|
||||
}
|
||||
|
||||
export async function getChannel(channelId: string): Promise<Channel> {
|
||||
const resp = await fetch(buildPath(`channels/${channelId}`));
|
||||
return await resp.json();
|
||||
}
|
||||
@@ -72,12 +72,6 @@ export interface Captions {
|
||||
url: string;
|
||||
};
|
||||
|
||||
export interface AuthorThumbnails {
|
||||
url: string;
|
||||
width: string;
|
||||
height: string;
|
||||
}
|
||||
|
||||
export interface VideoPlay extends Video {
|
||||
keywords: string[];
|
||||
likeCount: number;
|
||||
@@ -94,7 +88,7 @@ export interface VideoPlay extends Video {
|
||||
adaptiveFormats: AdaptiveFormats[];
|
||||
formatStreams: FormatStreams[];
|
||||
recommendedVideos: VideoBase[];
|
||||
authorThumbnails: AuthorThumbnails[];
|
||||
authorThumbnails: Image[];
|
||||
captions: Captions[];
|
||||
}
|
||||
|
||||
@@ -110,7 +104,7 @@ export interface ReturnYTDislikes {
|
||||
|
||||
export interface Comment {
|
||||
author: string;
|
||||
authorThumbnails: AuthorThumbnails[];
|
||||
authorThumbnails: Image[];
|
||||
authorID: string;
|
||||
authorUrl: string;
|
||||
isEdited: boolean;
|
||||
@@ -136,4 +130,23 @@ export interface Comments {
|
||||
videoId: string;
|
||||
continuation?: string;
|
||||
comments: Comment[];
|
||||
}
|
||||
|
||||
export interface Channel {
|
||||
author: string;
|
||||
authorId: string;
|
||||
authorUrl: string;
|
||||
authorVerified: boolean;
|
||||
authorBanners: Image[];
|
||||
authorThumbnails: Image[];
|
||||
subCount: number;
|
||||
totalViews: number;
|
||||
joined: number;
|
||||
autoGenerated: boolean;
|
||||
isFamilyFriendly: boolean;
|
||||
description: string;
|
||||
descriptionHml: string;
|
||||
allowedRegions: string[];
|
||||
tabs: string[];
|
||||
latestVideos: Video[];
|
||||
}
|
||||
@@ -1,7 +1,13 @@
|
||||
import humanNumber from "human-number";
|
||||
|
||||
export function truncate(value: string, maxLength: number = 50): string {
|
||||
return value.length > maxLength ? `${value.substring(0, maxLength)}...` : value;
|
||||
}
|
||||
|
||||
export function numberWithCommas(number: number) {
|
||||
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
export function cleanNumber(number: number): string {
|
||||
return humanNumber(number, (number: number) => Number.parseFloat(number.toString()).toFixed(1));
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<script lang="ts">
|
||||
import { cleanNumber } from '$lib/misc';
|
||||
import Thumbnail from '$lib/Thumbnail.svelte';
|
||||
|
||||
export let data;
|
||||
</script>
|
||||
|
||||
<div class="padding">
|
||||
{#if data.channel.authorBanners.length > 0}
|
||||
<img src={data.channel.authorBanners[0].url} width="100%" alt="Channel banner" />
|
||||
{/if}
|
||||
<div class="description">
|
||||
<img
|
||||
style="margin-right: 1em;"
|
||||
class="circle extra m l"
|
||||
src={data.channel.authorThumbnails[5].url}
|
||||
alt="Channel profile"
|
||||
/>
|
||||
<div>
|
||||
<h2>{data.channel.author}</h2>
|
||||
<p>{cleanNumber(data.channel.subCount)} subscribers</p>
|
||||
<p style="width: 60vw;">{data.channel.description}</p>
|
||||
</div>
|
||||
<button class="inverse-surface large">Subscribe</button>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<div class="grid padding">
|
||||
{#each data.channel.latestVideos as video}
|
||||
<div class="s12 m6 l2">
|
||||
<Thumbnail {video} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.description {
|
||||
display: flex;
|
||||
padding: 1em 0;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { getChannel } from '$lib/Api/index.js';
|
||||
|
||||
export async function load({ params }) {
|
||||
return {
|
||||
channel: await getChannel(params.slug)
|
||||
};
|
||||
}
|
||||
@@ -1,22 +1,17 @@
|
||||
<script lang="ts">
|
||||
import humanNumber from 'human-number';
|
||||
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
import Plyr from 'plyr';
|
||||
import 'plyr/dist/plyr.css';
|
||||
|
||||
import Thumbnail from '$lib/Thumbnail.svelte';
|
||||
import { numberWithCommas } from '$lib/misc.js';
|
||||
import { cleanNumber, numberWithCommas } from '$lib/misc.js';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import { invidiousInstance } from '../../../store';
|
||||
|
||||
export let data;
|
||||
|
||||
const cleanRound = (number: number) => Number.parseFloat(number.toString()).toFixed(1);
|
||||
|
||||
$: video = data.video;
|
||||
let player;
|
||||
onMount(() => {
|
||||
player = new Plyr('#player');
|
||||
@@ -65,11 +60,11 @@
|
||||
<nav class="no-space m l">
|
||||
<button style="cursor: default;" class="border left-round">
|
||||
<i class="small">thumb_up</i>
|
||||
<span>{humanNumber(data.returnYTDislikes.likes, cleanRound)}</span>
|
||||
<span>{cleanNumber(data.returnYTDislikes.likes)}</span>
|
||||
</button>
|
||||
<button style="cursor: default;" class="border right-round">
|
||||
<i class="small">thumb_down_alt</i>
|
||||
<span>{humanNumber(data.returnYTDislikes.dislikes, cleanRound)}</span>
|
||||
<span>{cleanNumber(data.returnYTDislikes.dislikes)}</span>
|
||||
</button>
|
||||
</nav>
|
||||
<button class="border m l" data-ui="#share"
|
||||
@@ -85,11 +80,11 @@
|
||||
<nav class="no-space s">
|
||||
<button style="cursor: default;" class="border left-round">
|
||||
<i class="small">thumb_up</i>
|
||||
<span>{humanNumber(data.returnYTDislikes.likes, cleanRound)}</span>
|
||||
<span>{cleanNumber(data.returnYTDislikes.likes)}</span>
|
||||
</button>
|
||||
<button style="cursor: default;" class="border right-round">
|
||||
<i class="small">thumb_down_alt</i>
|
||||
<span>{humanNumber(data.returnYTDislikes.dislikes, cleanRound)}</span>
|
||||
<span>{cleanNumber(data.returnYTDislikes.dislikes)}</span>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user