Implemented on device watch history
This commit is contained in:
@@ -74,6 +74,8 @@ import {
|
||||
saveWatchHistoryBackend,
|
||||
updateWatchHistoryBackend
|
||||
} from './backend/history';
|
||||
import { localDb } from '$lib/dexie';
|
||||
import { getBestThumbnail } from '$lib/images';
|
||||
|
||||
export async function getPopular(fetchOptions?: RequestInit): Promise<Video[]> {
|
||||
// Doesn't exist in YTjs.
|
||||
@@ -288,6 +290,30 @@ export async function getWatchHistory(
|
||||
if (isOwnBackend()?.internalAuth && get(rawMasterKeyStore)) {
|
||||
return getWatchHistoryBackend(options);
|
||||
}
|
||||
|
||||
let watchHistory = await localDb.watchHistory.toArray();
|
||||
watchHistory.sort((a, b) => b.watched.getDate() - a.watched.getDate());
|
||||
|
||||
if (options.videoIds) {
|
||||
watchHistory = watchHistory.filter((item) => !options.videoIds?.includes(item.videoId));
|
||||
}
|
||||
|
||||
const cullAfter = 1000;
|
||||
if (watchHistory.length > cullAfter) {
|
||||
const videosToDelete = watchHistory.slice(cullAfter);
|
||||
const videoIdsToDelete = videosToDelete.map((video) => video.videoId);
|
||||
await localDb.watchHistory.where('videoId').anyOf(videoIdsToDelete).delete();
|
||||
|
||||
// Don't display culled videos.
|
||||
watchHistory = watchHistory.slice(0, cullAfter);
|
||||
}
|
||||
|
||||
const maxResults = 100;
|
||||
|
||||
const start = (options.page ?? 1 - 1) * maxResults;
|
||||
const end = start + maxResults;
|
||||
|
||||
return watchHistory.splice(start, end);
|
||||
}
|
||||
|
||||
export async function getVideoWatchHistory(
|
||||
@@ -296,12 +322,16 @@ export async function getVideoWatchHistory(
|
||||
if (isOwnBackend()?.internalAuth && get(rawMasterKeyStore)) {
|
||||
return getVideoWatchHistoryBackend(videoId);
|
||||
}
|
||||
|
||||
return await localDb.watchHistory.get({ videoId });
|
||||
}
|
||||
|
||||
export async function deleteWatchHistory() {
|
||||
if (isOwnBackend()?.internalAuth && get(rawMasterKeyStore)) {
|
||||
return deleteWatchHistoryBackend();
|
||||
}
|
||||
|
||||
await localDb.watchHistory.clear();
|
||||
}
|
||||
|
||||
export async function updateWatchHistory(
|
||||
@@ -314,12 +344,28 @@ export async function updateWatchHistory(
|
||||
}
|
||||
|
||||
if (get(invidiousAuthStore)) postHistoryInvidious(videoId, fetchOptions);
|
||||
|
||||
await localDb.watchHistory.update({ videoId }, { progress });
|
||||
}
|
||||
|
||||
export async function saveWatchHistory(video: VideoPlay, progress: number = 0) {
|
||||
if (isOwnBackend()?.internalAuth && get(rawMasterKeyStore)) {
|
||||
return saveWatchHistoryBackend(video, progress);
|
||||
}
|
||||
|
||||
if (await localDb.watchHistory.get({ videoId: video.videoId })) return;
|
||||
|
||||
await localDb.watchHistory.add({
|
||||
author: video.author,
|
||||
watched: new Date(),
|
||||
lengthSeconds: video.lengthSeconds,
|
||||
progress,
|
||||
id: video.videoId,
|
||||
title: video.title,
|
||||
thumbnail: getBestThumbnail(video.videoThumbnails),
|
||||
videoId: video.videoId,
|
||||
type: 'historyVideo'
|
||||
});
|
||||
}
|
||||
|
||||
export async function getPlaylist(
|
||||
|
||||
@@ -21,11 +21,11 @@ export class MaterialiousDb extends Dexie {
|
||||
|
||||
constructor() {
|
||||
super('materialious');
|
||||
this.version(2).stores({
|
||||
this.version(3).stores({
|
||||
favouriteChannels: 'channelId',
|
||||
channelSubscriptions: 'channelId',
|
||||
subscriptionFeed: 'videoId, authorId, published',
|
||||
watchHistory: 'videoId, id'
|
||||
watchHistory: 'videoId'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,16 +26,14 @@ export function getPages(): Pages {
|
||||
href: '/playlists',
|
||||
name: get(_)('pages.playlists'),
|
||||
requiresAuth: true
|
||||
}
|
||||
];
|
||||
|
||||
if (isOwnBackend()?.internalAuth && get(rawMasterKeyStore))
|
||||
pages.push({
|
||||
},
|
||||
{
|
||||
icon: 'history',
|
||||
href: '/history',
|
||||
name: get(_)('pages.history'),
|
||||
requiresAuth: false
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
pages = pages.filter((page) => {
|
||||
return !page.requiresAuth || (get(invidiousAuthStore) && !isYTBackend());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { resolve } from '$app/paths';
|
||||
import { getPopular, HTTPError } from '$lib/api/index';
|
||||
import { getPopular } from '$lib/api/index';
|
||||
import { HTTPError } from '$lib/api/invidious/request';
|
||||
import { isYTBackend } from '$lib/misc';
|
||||
import { feedCacheStore, invidiousInstanceStore } from '$lib/store';
|
||||
import { error, redirect } from '@sveltejs/kit';
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
import { resolve } from '$app/paths';
|
||||
import { getWatchHistoryBackend } from '$lib/api/backend/history';
|
||||
import { isOwnBackend } from '$lib/shared';
|
||||
import { rawMasterKeyStore } from '$lib/store';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { get } from 'svelte/store';
|
||||
import { getWatchHistory } from '$lib/api';
|
||||
|
||||
export async function load() {
|
||||
if (!isOwnBackend()?.internalAuth || !get(rawMasterKeyStore))
|
||||
throw redirect(302, resolve('/', {}));
|
||||
|
||||
return { videos: await getWatchHistoryBackend() };
|
||||
return { videos: await getWatchHistory() };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user