feat: add mark as watched/unwatched button

This commit is contained in:
HiImKobeAnd 2024-08-02 20:11:10 +02:00
parent aa9850830a
commit 095cd1869f
4 changed files with 57 additions and 2 deletions

View File

@ -48,7 +48,7 @@
<LoadingIndicatorPage :show-content="videosStore != null" class="video-grid"> <LoadingIndicatorPage :show-content="videosStore != null" class="video-grid">
<template v-for="video in filteredVideos" :key="video.url"> <template v-for="video in filteredVideos" :key="video.url">
<VideoItem v-if="shouldShowVideo(video)" :is-feed="true" :item="video" /> <VideoItem v-if="shouldShowVideo(video)" :is-feed="true" :item="video" @update:watched="onUpdateWatched" />
</template> </template>
</LoadingIndicatorPage> </LoadingIndicatorPage>
</template> </template>
@ -140,6 +140,15 @@ export default {
this.loadMoreVideos(); this.loadMoreVideos();
} }
}, },
onUpdateWatched(urls = null) {
if (urls === null) {
if (this.videos.length > 0) this.updateWatched(this.videos);
return;
}
const subset = this.videos.filter(({ url }) => urls.includes(url));
if (subset.length > 0) this.updateWatched(subset);
},
shouldShowVideo(video) { shouldShowVideo(video) {
switch (this.selectedFilter.toLowerCase()) { switch (this.selectedFilter.toLowerCase()) {
case "shorts": case "shorts":

View File

@ -122,6 +122,11 @@
> >
<i class="i-fa6-solid:circle-minus" /> <i class="i-fa6-solid:circle-minus" />
</button> </button>
<!-- TODO hide watchButton if history is disabled -->
<button ref="watchButton" @click="toggleWatched(item.url.substr(-11))">
<i v-if="item.watched" :title="$t('actions.mark_as_unwatched')" class="i-fa6-solid:eye-slash" />
<i v-else :title="$t('actions.mark_as_watched')" class="i-fa6-solid:eye" />
</button>
<ConfirmModal <ConfirmModal
v-if="showConfirmRemove" v-if="showConfirmRemove"
:message="$t('actions.delete_playlist_video_confirm')" :message="$t('actions.delete_playlist_video_confirm')"
@ -171,7 +176,7 @@ export default {
preferListen: { type: Boolean, default: false }, preferListen: { type: Boolean, default: false },
admin: { type: Boolean, default: false }, admin: { type: Boolean, default: false },
}, },
emits: ["remove"], emits: ["update:watched", "remove"],
data() { data() {
return { return {
showPlaylistModal: false, showPlaylistModal: false,
@ -212,6 +217,40 @@ export default {
} }
}; };
}, },
toggleWatched(videoId) {
if (window.db) {
// Should match WatchVideo.vue
var tx = window.db.transaction("watch_history", "readwrite");
var store = tx.objectStore("watch_history");
var instance = this;
var request = store.get(videoId);
request.onsuccess = function (event) {
var video = event.target.result;
if (video) {
video.watchedAt = Date.now();
} else {
// Should match WatchVideo.vue
video = {
videoId: videoId,
title: instance.item.title,
duration: instance.item.duration,
thumbnail: instance.item.thumbnailUrl,
uploaderUrl: instance.item.uploaderUrl,
uploaderName: instance.item.uploader,
watchedAt: Date.now(),
};
}
// Set time to end for shouldShowVideo
video.currentTime =
instance.item.currentTime !== instance.item.duration ? instance.item.duration : 0;
// Save
store.put(video);
// Disappear if hideWatched is on
instance.$emit("update:watched", [instance.item.url]);
instance.shouldShowVideo();
};
}
},
}, },
}; };
</script> </script>

View File

@ -132,6 +132,8 @@
"show_chapters": "Chapters", "show_chapters": "Chapters",
"store_search_history": "Store Search History", "store_search_history": "Store Search History",
"hide_watched": "Hide watched videos in the feed", "hide_watched": "Hide watched videos in the feed",
"mark_as_watched": "Mark as Watched",
"mark_as_unwatched": "Mark as Unwatched",
"documentation": "Documentation", "documentation": "Documentation",
"status_page": "Status", "status_page": "Status",
"source_code": "Source code", "source_code": "Source code",

View File

@ -144,6 +144,11 @@ const mixin = {
var request = store.get(video.url.substr(-11)); var request = store.get(video.url.substr(-11));
request.onsuccess = function (event) { request.onsuccess = function (event) {
if (event.target.result) { if (event.target.result) {
if (event.target.result.currentTime == 0) {
video.watched = false;
video.currentTime = event.target.result.currentTime;
return;
}
video.watched = true; video.watched = true;
video.currentTime = event.target.result.currentTime; video.currentTime = event.target.result.currentTime;
} }