diff --git a/materialious/src/lib/api/backend/history.ts b/materialious/src/lib/api/backend/history.ts index fafb6220..90e4eca7 100644 --- a/materialious/src/lib/api/backend/history.ts +++ b/materialious/src/lib/api/backend/history.ts @@ -73,7 +73,7 @@ export async function getVideoWatchHistory( } export async function getWatchHistory( - options: { page?: number; videoIds?: string[] } = { page: 0, videoIds: undefined } + options: { page?: number; videoIds?: string[] } = { page: undefined, videoIds: undefined } ): Promise { await sodium.ready; const rawKey = await getRawKey(); @@ -86,9 +86,17 @@ export async function getWatchHistory( } } - const resp = await fetch( - `/api/user/history?page=${options.page}${videoHashes.length > 0 ? '&videoHashes=' + videoHashes.join(',') : ''}` - ); + const params = new URLSearchParams(); + + if (options.page) { + params.set('page', options.page.toString()); + } + + if (options.videoIds && options.videoIds.length > 0) { + params.set('videoHashes', videoHashes.join(',')); + } + + const resp = await fetch(`/api/user/history?${params.toString()}`); if (!resp.ok) return []; const rawHistory = await resp.json(); @@ -102,6 +110,10 @@ export async function getWatchHistory( return history; } +export async function deleteWatchHistory() { + await fetch('/api/user/history', { method: 'DELETE' }); +} + export async function saveWatchHistory(video: VideoPlay, progress: number = 0) { await sodium.ready; const rawKey = await getRawKey(); diff --git a/materialious/src/lib/components/thumbnail/VideoThumbnail.svelte b/materialious/src/lib/components/thumbnail/VideoThumbnail.svelte index 37d83d25..cbd4ed6f 100644 --- a/materialious/src/lib/components/thumbnail/VideoThumbnail.svelte +++ b/materialious/src/lib/components/thumbnail/VideoThumbnail.svelte @@ -41,6 +41,8 @@ let watchUrl = createVideoUrl(video.videoId, playlistId); + let beenWatched: boolean = $state(false); + syncPartyPeerStore.subscribe((peer) => { if (peer) { watchUrl.searchParams.set('sync', peer.id); @@ -69,6 +71,10 @@ } else sideways = true; } + function checkIfWatched() { + beenWatched = !!(progress && !page.url.pathname.endsWith('/history')); + } + onMount(async () => { calcThumbnailPlaceholderHeight(); @@ -80,11 +86,15 @@ calcThumbnailPlaceholderHeight(); }); - queueGetWatchHistory(video.videoId).then((watchHistory) => { - if (watchHistory) { - progress = watchHistory.progress.toString(); - } - }); + checkIfWatched(); + + if (!page.url.pathname.endsWith('/history')) + queueGetWatchHistory(video.videoId).then((watchHistory) => { + if (watchHistory) { + progress = watchHistory.progress.toString(); + checkIfWatched(); + } + }); if (get(interfaceLowBandwidthMode)) return; @@ -176,8 +186,6 @@ onclick={onVideoSelected} > {#if !$interfaceLowBandwidthMode} - {@const beenWatched = progress && !page.url.pathname.endsWith('/history')} -
{#if !thumbnail}
+ import { deleteWatchHistory, getWatchHistory } from '$lib/api/backend/history'; import ItemsList from '$lib/components/layout/ItemsList.svelte'; + import InfiniteLoading, { type InfiniteEvent } from 'svelte-infinite-loading'; + import { _ } from '$lib/i18n'; let { data } = $props(); + + let currentPage = 1; + async function loadMore(event: InfiniteEvent) { + currentPage++; + + const history = await getWatchHistory({ page: currentPage }); + if (history.length === 0) { + event.detail.complete(); + } else { + data.videos = [...data.videos, ...history]; + event.detail.loaded(); + } + } + + async function deleteHistory() { + await deleteWatchHistory(); + data.videos = []; + } +{#if data.videos.length > 0} + +
+{/if} + + diff --git a/materialious/src/routes/(app)/watch/[slug]/+page.svelte b/materialious/src/routes/(app)/watch/[slug]/+page.svelte index 327b296d..325349b8 100644 --- a/materialious/src/routes/(app)/watch/[slug]/+page.svelte +++ b/materialious/src/routes/(app)/watch/[slug]/+page.svelte @@ -41,7 +41,7 @@ import { page } from '$app/state'; import Share from '$lib/components/Share.svelte'; import Playlist from '$lib/components/watch/Playlist.svelte'; - import type { PlayerEvents } from '$lib/player/index.js'; + import type { PlayerEvents } from '$lib/player/index'; let { data = $bindable() } = $props(); diff --git a/materialious/src/routes/api/user/history/+server.ts b/materialious/src/routes/api/user/history/+server.ts index 630ee601..1073b6af 100644 --- a/materialious/src/routes/api/user/history/+server.ts +++ b/materialious/src/routes/api/user/history/+server.ts @@ -1,4 +1,4 @@ -import { getSequelize } from '$lib/server/database.js'; +import { getSequelize } from '$lib/server/database'; import { error, json } from '@sveltejs/kit'; import z from 'zod'; import { Op } from 'sequelize'; diff --git a/materialious/src/routes/api/user/history/[videoHash]/+server.ts b/materialious/src/routes/api/user/history/[videoHash]/+server.ts index 2d827dd3..e84f9516 100644 --- a/materialious/src/routes/api/user/history/[videoHash]/+server.ts +++ b/materialious/src/routes/api/user/history/[videoHash]/+server.ts @@ -1,4 +1,4 @@ -import { getSequelize } from '$lib/server/database.js'; +import { getSequelize } from '$lib/server/database'; import { error, json } from '@sveltejs/kit'; import z from 'zod'; diff --git a/materialious/src/routes/api/user/keyValue/[key]/+server.ts b/materialious/src/routes/api/user/keyValue/[key]/+server.ts index 26bdd8f3..3208b5fd 100644 --- a/materialious/src/routes/api/user/keyValue/[key]/+server.ts +++ b/materialious/src/routes/api/user/keyValue/[key]/+server.ts @@ -1,5 +1,5 @@ -import { persistedStoreKeys } from '$lib/externalSettings/settings.js'; -import { getUser } from '$lib/server/user.js'; +import { persistedStoreKeys } from '$lib/externalSettings/settings'; +import { getUser } from '$lib/server/user'; import { error, json } from '@sveltejs/kit'; import z from 'zod';