More watch page progress
This commit is contained in:
Generated
+30
@@ -9,6 +9,7 @@
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"beercss": "^3.5.1",
|
||||
"human-number": "^2.0.4",
|
||||
"svelte-persisted-store": "^0.9.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -16,6 +17,7 @@
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@types/eslint": "^8.56.0",
|
||||
"@types/human-number": "^1.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
"@typescript-eslint/parser": "^7.0.0",
|
||||
"eslint": "^8.56.0",
|
||||
@@ -925,6 +927,12 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
||||
},
|
||||
"node_modules/@types/human-number": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/human-number/-/human-number-1.0.2.tgz",
|
||||
"integrity": "sha512-Xm2hW0MXOjX/IOrRv8IRLycwVz23cU51b3fUn3Km5q8+4oM88uJaZ36dD1S0qINg92jhfQm7iEuAxZefIIffYg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
@@ -2186,6 +2194,17 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/human-number": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/human-number/-/human-number-2.0.4.tgz",
|
||||
"integrity": "sha512-OENvA941poJU1VGR6s5Nf/GpYNPE+81lmHkIVLO9FgiyHxB+BSlVOJV3lnItk5tfHzcEbZv3kTQrzpZK0+ExRA==",
|
||||
"dependencies": {
|
||||
"round-to": "~5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
|
||||
@@ -2958,6 +2977,17 @@
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/round-to": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/round-to/-/round-to-5.0.0.tgz",
|
||||
"integrity": "sha512-i4+Ntwmo5kY7UWWFSDEVN3RjT2PX1FqkZ9iCcAO3sKML3Ady9NgsjM/HLdYKUAnrxK4IlSvXzpBMDvMHZQALRQ==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@types/eslint": "^8.56.0",
|
||||
"@types/human-number": "^1.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||
"@typescript-eslint/parser": "^7.0.0",
|
||||
"eslint": "^8.56.0",
|
||||
@@ -32,6 +33,7 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"beercss": "^3.5.1",
|
||||
"human-number": "^2.0.4",
|
||||
"svelte-persisted-store": "^0.9.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { get } from 'svelte/store';
|
||||
import { invidiousInstance } from '../../store';
|
||||
import type { Video, VideoPlay } from './model';
|
||||
import { invidiousInstance, returnYTDislikesInstance } from '../../store';
|
||||
import type { ReturnYTDislikes, Video, VideoPlay } from './model';
|
||||
|
||||
function buildPath(path: string): string {
|
||||
return `${get(invidiousInstance)}/api/v1/${path}`;
|
||||
@@ -14,4 +14,9 @@ export async function getTrending(): Promise<Video[]> {
|
||||
export async function getVideo(videoId: string): Promise<VideoPlay> {
|
||||
const resp = await fetch(buildPath(`videos/${videoId}`));
|
||||
return await resp.json();
|
||||
}
|
||||
|
||||
export async function getDislikes(videoId: string): Promise<ReturnYTDislikes> {
|
||||
const resp = await fetch(`${get(returnYTDislikesInstance)}/Votes?videoId=${videoId}`);
|
||||
return await resp.json();
|
||||
}
|
||||
@@ -72,6 +72,12 @@ export interface Captions {
|
||||
url: string;
|
||||
};
|
||||
|
||||
export interface AuthorThumbnails {
|
||||
url: string;
|
||||
width: string;
|
||||
height: string;
|
||||
}
|
||||
|
||||
export interface VideoPlay extends Video {
|
||||
keywords: string[];
|
||||
likeCount: number;
|
||||
@@ -88,4 +94,15 @@ export interface VideoPlay extends Video {
|
||||
adaptiveFormats: AdaptiveFormats[];
|
||||
formatStreams: FormatStreams;
|
||||
recommendedVideos: VideoBase[];
|
||||
authorThumbnails: AuthorThumbnails[];
|
||||
}
|
||||
|
||||
export interface ReturnYTDislikes {
|
||||
id: string;
|
||||
dateCreated: string;
|
||||
likes: number;
|
||||
dislikes: number;
|
||||
rating: number;
|
||||
viewCount: number;
|
||||
deleted: boolean;
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
<script lang="ts">
|
||||
import Logo from '$lib/Logo.svelte';
|
||||
|
||||
import 'beercss';
|
||||
import 'material-dynamic-colors';
|
||||
|
||||
const pages = [
|
||||
{
|
||||
icon: 'home',
|
||||
|
||||
@@ -1,3 +1 @@
|
||||
import 'beercss/dist/cdn/beer.min.css';
|
||||
import 'material-dynamic-colors';
|
||||
|
||||
export let ssr = false;
|
||||
@@ -1,19 +1,51 @@
|
||||
<script lang="ts">
|
||||
import Thumbnail from '$lib/Thumbnail.svelte';
|
||||
import { numberWithCommas } from '$lib/misc.js';
|
||||
import humanNumber from 'human-number';
|
||||
|
||||
export let data;
|
||||
|
||||
const cleanRound = (number: number) => Number.parseFloat(number.toString()).toFixed(1);
|
||||
</script>
|
||||
|
||||
<div class="grid large-margin">
|
||||
<div class="s12 m10 l10">
|
||||
<div class="s12 m12 l10">
|
||||
<h5>{data.video.title}</h5>
|
||||
|
||||
<nav>
|
||||
<img class="circle large" src={data.video.authorThumbnails[2].url} alt="Channel profile" />
|
||||
<div>
|
||||
<p class="bold">{data.video.author}</p>
|
||||
<p>{data.video.subCountText}</p>
|
||||
</div>
|
||||
<button class="inverse-surface">Subscribe</button>
|
||||
<div class="max"></div>
|
||||
<nav class="no-space">
|
||||
<button style="cursor: default;" class="border left-round">
|
||||
<i class="small">thumb_up</i>
|
||||
<span>{humanNumber(data.returnYTDislikes.likes, cleanRound)}</span>
|
||||
</button>
|
||||
<button style="cursor: default;" class="border right-round">
|
||||
<i class="small">thumb_down_alt</i>
|
||||
<span>{humanNumber(data.returnYTDislikes.dislikes, cleanRound)}</span>
|
||||
</button>
|
||||
</nav>
|
||||
<button class="border" data-ui="#share"
|
||||
><i>share</i> Share
|
||||
<menu class="left no-wrap" id="share" data-ui="#share">
|
||||
<a class="row"> <div class="min">Copy Materialious link</div></a><a class="row">
|
||||
<div class="min">Copy Invidious redirect link</div></a
|
||||
><a class="row"> <div class="min">Copy Youtube link</div></a></menu
|
||||
></button
|
||||
>
|
||||
</nav>
|
||||
|
||||
<article>
|
||||
<p>{numberWithCommas(data.video.viewCount)} views • {data.video.publishedText}</p>
|
||||
<p style="white-space: pre-line">{data.video.description}</p>
|
||||
<p style="white-space: pre-line;word-wrap: break-word;">{data.video.description}</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="m4 l2">
|
||||
<div class="s12 m12 l2">
|
||||
{#each data.video.recommendedVideos as recommendedVideo}
|
||||
<Thumbnail video={recommendedVideo} />
|
||||
{/each}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getVideo } from '$lib/Api/index.js';
|
||||
import { getDislikes, getVideo } from '$lib/Api/index.js';
|
||||
|
||||
export async function load({ params }) {
|
||||
return { video: await getVideo(params.slug) };
|
||||
return { video: await getVideo(params.slug), returnYTDislikes: await getDislikes(params.slug) };
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { persisted } from 'svelte-persisted-store';
|
||||
|
||||
export const invidiousInstance = persisted('invidiousInstance', import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE);
|
||||
export const returnYTDislikesInstance = persisted('returnYTDislikesInstance', import.meta.env.VITE_DEFAULT_RETURNYTDISLIKES_INSTANCE);
|
||||
Reference in New Issue
Block a user