diff --git a/materialious/src/lib/api/invidious/channel.ts b/materialious/src/lib/api/invidious/channel.ts index 98212cb3..a49e4e84 100644 --- a/materialious/src/lib/api/invidious/channel.ts +++ b/materialious/src/lib/api/invidious/channel.ts @@ -1,3 +1,4 @@ +import { associateAvatar } from '$lib/thumbnail'; import type { ChannelContent, ChannelOptions, ChannelPage } from '../model'; import { buildPath, fetchErrorHandle } from './request'; @@ -8,7 +9,13 @@ export async function getChannelInvidious( const resp = await fetchErrorHandle( await fetch(buildPath(`channels/${channelId}`), fetchOptions) ); - return await resp.json(); + const respJson = await resp.json(); + + if (resp.ok) { + associateAvatar(channelId, respJson.authorBanners); + } + + return respJson; } export async function getChannelContentInvidious( diff --git a/materialious/src/lib/api/invidious/video.ts b/materialious/src/lib/api/invidious/video.ts index 0bd15d5b..bfd3fd23 100644 --- a/materialious/src/lib/api/invidious/video.ts +++ b/materialious/src/lib/api/invidious/video.ts @@ -4,6 +4,7 @@ import { buildPath, fetchErrorHandle } from './request'; import { getVideoYTjs } from '../youtubejs/video'; import { playerYouTubeJsFallback } from '$lib/store'; import { isUnrestrictedPlatform } from '$lib/misc'; +import { associateAvatar } from '$lib/thumbnail'; export async function getVideoInvidious( videoId: string, @@ -20,5 +21,12 @@ export async function getVideoInvidious( } else { await fetchErrorHandle(resp); } - return await resp.json(); + + const respJson = await resp.json(); + + if (resp.ok) { + associateAvatar(respJson.authorId, respJson.authorThumbnails); + } + + return respJson; } diff --git a/materialious/src/lib/api/youtubejs/channel.ts b/materialious/src/lib/api/youtubejs/channel.ts index fd77bc6a..82240788 100644 --- a/materialious/src/lib/api/youtubejs/channel.ts +++ b/materialious/src/lib/api/youtubejs/channel.ts @@ -9,6 +9,7 @@ import type { Video } from '../model'; import { invidiousItemSchema } from './schema'; +import { associateAvatar } from '$lib/thumbnail'; export async function getChannelYTjs(channelId: string): Promise { const innertube = await getInnertube(); @@ -23,6 +24,7 @@ export async function getChannelYTjs(channelId: string): Promise { innerResults.header.content?.is(YTNodes.PageHeaderView) ) { authorBanners = innerResults.header.content.banner?.image ?? []; + associateAvatar(channelId, authorBanners); } const description = innerResults.metadata.description ?? ''; diff --git a/materialious/src/lib/api/youtubejs/video.ts b/materialious/src/lib/api/youtubejs/video.ts index f9d89d3e..1c245cf1 100644 --- a/materialious/src/lib/api/youtubejs/video.ts +++ b/materialious/src/lib/api/youtubejs/video.ts @@ -17,6 +17,7 @@ import { Utils, YT, YTNodes, Platform, type IGetChallengeResponse } from 'youtub import { getInnertube } from '.'; import { isUnrestrictedPlatform } from '$lib/misc'; import { webPoTokenMinter } from '$lib/web/youtube/minter'; +import { associateAvatar } from '$lib/thumbnail'; Platform.shim.eval = async ( data: Types.BuildScriptResult, @@ -149,6 +150,8 @@ export async function getVideoYTjs(videoId: string): Promise { if (video.basic_info.channel_id) { const channel = await innertube.getChannel(video.basic_info.channel_id); authorThumbnails = channel.metadata.avatar as Image[]; + + associateAvatar(video.basic_info.channel_id, authorThumbnails); } else { authorThumbnails = []; } diff --git a/materialious/src/lib/components/thumbnail/VideoThumbnail.svelte b/materialious/src/lib/components/thumbnail/VideoThumbnail.svelte index f3996605..d00a75a1 100644 --- a/materialious/src/lib/components/thumbnail/VideoThumbnail.svelte +++ b/materialious/src/lib/components/thumbnail/VideoThumbnail.svelte @@ -19,6 +19,8 @@ import { queueGetWatchHistory } from '$lib/api/historyPool'; import { page } from '$app/state'; import { getDeArrow, getThumbnailDeArrow } from '$lib/api/dearrow'; + import { avatarFromChannelId } from '$lib/thumbnail'; + import { mergeAttrs } from 'melt'; interface Props { video: VideoBase | Video | Notification | PlaylistPageVideo | VideoWatchHistory; @@ -70,6 +72,7 @@ } let thumbnailHeight = $state(0); + let thumbnailHTMLElement: HTMLImageElement | undefined = $state(); const thumbnail = new Avatar({ src: () => thumbnailSrc, @@ -78,7 +81,10 @@ } }); - let thumbnailHTMLElement: HTMLImageElement | undefined = $state(); + let authorAvatarSrc = $state(''); + const authorAvatar = new Avatar({ + src: () => authorAvatarSrc + }); let startedSideways = sideways === true; function disableSideways() { @@ -90,6 +96,12 @@ } onMount(async () => { + if ('authorId' in video) { + avatarFromChannelId(video.authorId).then((url) => { + if (url) authorAvatarSrc = url; + }); + } + // Check if sideways should be enabled or disabled. disableSideways(); @@ -181,39 +193,50 @@ {letterCase(video.title.trimEnd())} -
- {#if 'authorId' in video && video.authorId} - {video.author} - - {:else} -

{video.author}

+
+ diff --git a/materialious/src/lib/dexie.ts b/materialious/src/lib/dexie.ts index 982d4714..80851826 100644 --- a/materialious/src/lib/dexie.ts +++ b/materialious/src/lib/dexie.ts @@ -13,19 +13,27 @@ export interface ChannelSubscriptions { lastRSSFetch: Date; } +export interface ChannelAvatars { + channelId: string; + avatarUrl: string; + updated: Date; +} + export class MaterialiousDb extends Dexie { favouriteChannels!: Table; channelSubscriptions!: Table; subscriptionFeed!: Table