Added channel to search results
This commit is contained in:
Generated
+4
-4
@@ -13,7 +13,7 @@
|
||||
"media-icons": "^0.10.0",
|
||||
"sponsorblock-api": "^0.2.4",
|
||||
"svelte-persisted-store": "^0.9.1",
|
||||
"vidstack": "^1.10.9"
|
||||
"vidstack": "^1.11.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
@@ -3573,9 +3573,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/vidstack": {
|
||||
"version": "1.10.9",
|
||||
"resolved": "https://registry.npmjs.org/vidstack/-/vidstack-1.10.9.tgz",
|
||||
"integrity": "sha512-YjaCdQxsRrhQpdR48jtNhusMrC5009BWQ3KtFhBzAMEDN23wW5qLNqdWfSgXVogZdpk/C2W/+79HcdDiW12PYg==",
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/vidstack/-/vidstack-1.11.1.tgz",
|
||||
"integrity": "sha512-j0vxUIB96ctKusO/vDe+lm+UGJ6MU5BfFPOcleQti2Hx3VeyMBP4oE51eJUiK1Tr52a1CXFTURL7A47GI+xI3A==",
|
||||
"dependencies": {
|
||||
"media-captions": "^1.0.1",
|
||||
"unplugin": "^1.6.0"
|
||||
|
||||
@@ -38,6 +38,6 @@
|
||||
"media-icons": "^0.10.0",
|
||||
"sponsorblock-api": "^0.2.4",
|
||||
"svelte-persisted-store": "^0.9.1",
|
||||
"vidstack": "^1.10.9"
|
||||
"vidstack": "^1.11.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { get } from 'svelte/store';
|
||||
import { auth, returnYTDislikesInstance } from '../../store';
|
||||
import type { Channel, Comments, ReturnYTDislikes, SearchSuggestion, Subscription, Video, VideoPlay } from './model';
|
||||
import type { Channel, ChannelPage, Comments, ReturnYTDislikes, SearchSuggestion, Subscription, Video, VideoPlay } from './model';
|
||||
|
||||
export function buildPath(path: string): string {
|
||||
return `${import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE}/api/v1/${path}`;
|
||||
@@ -26,7 +26,7 @@ export async function getVideo(videoId: string, local: boolean = false): Promise
|
||||
}
|
||||
|
||||
export async function getDislikes(videoId: string): Promise<ReturnYTDislikes> {
|
||||
const resp = await fetch(`${get(returnYTDislikesInstance)}/Votes?videoId=${videoId}`);
|
||||
const resp = await fetch(`${get(returnYTDislikesInstance)}/votes?videoId=${videoId}`);
|
||||
return await resp.json();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ export async function getComments(videoId: string, parameters: {
|
||||
return await resp.json();
|
||||
}
|
||||
|
||||
export async function getChannel(channelId: string): Promise<Channel> {
|
||||
export async function getChannel(channelId: string): Promise<ChannelPage> {
|
||||
const resp = await fetch(buildPath(`channels/${channelId}`));
|
||||
return await resp.json();
|
||||
}
|
||||
@@ -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<Video[]> {
|
||||
}): Promise<(Channel | Video)[]> {
|
||||
if (typeof options.sort_by === "undefined") {
|
||||
options.sort_by = "relevance";
|
||||
}
|
||||
|
||||
@@ -146,22 +146,26 @@ export interface Comments {
|
||||
}
|
||||
|
||||
export interface Channel {
|
||||
type: "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;
|
||||
authorThumbnails: Image[];
|
||||
}
|
||||
|
||||
export interface ChannelPage extends Channel {
|
||||
allowedRegions: string[];
|
||||
tabs: string[];
|
||||
latestVideos: Video[];
|
||||
isFamilyFriendly: boolean;
|
||||
joined: number;
|
||||
authorBanners: Image[];
|
||||
}
|
||||
|
||||
export interface SearchSuggestion {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<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>
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { getSearch } from '$lib/Api';
|
||||
import VideoList from '$lib/VideoList.svelte';
|
||||
import Channel from '$lib/Channel.svelte';
|
||||
import Thumbnail from '$lib/Thumbnail.svelte';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { activePage } from '../../../store';
|
||||
|
||||
@@ -50,4 +51,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<VideoList videos={search} />
|
||||
<div class="page right active">
|
||||
<div class="space"></div>
|
||||
<div class="grid">
|
||||
{#each search as item}
|
||||
<div class="s12 m6 l2">
|
||||
<article class="no-padding" style="height: 100%;">
|
||||
{#if item.type === 'video'}
|
||||
<Thumbnail video={item} />
|
||||
{:else if item.type === 'channel'}
|
||||
<Channel channel={item} />
|
||||
{/if}
|
||||
</article>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { getSearch } from '$lib/Api/index.js';
|
||||
|
||||
export async function load({ params }) {
|
||||
return {
|
||||
search: await getSearch(params.slug, { type: "video" }),
|
||||
search: await getSearch(params.slug, { type: "all" }),
|
||||
slug: params.slug
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user