feat: added local history (#609)

This commit is contained in:
Fergus Lai 2023-03-30 02:09:11 +01:00 committed by GitHub
parent 405531a03b
commit f7ce9a62ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 214 additions and 2 deletions

View File

@ -0,0 +1,101 @@
<template>
<v-card
v-ripple
class="background d-flex flex-row overflow-hidden mb-4 mx-4"
style="height: 4.5rem !important"
:class="
$store.state.tweaks.roundThumb && $store.state.tweaks.roundTweak > 0
? $vuetify.theme.dark
? 'lighten-1'
: 'darken-1'
: ''
"
:style="{
borderRadius: $store.state.tweaks.roundThumb
? `${$store.state.tweaks.roundTweak / 3}rem`
: '0',
}"
flat
>
<v-card
class="d-flex flex-row w-50 elevation-0"
:to="`/watch?v=${video.id}`"
>
<v-img
:src="thumbnail"
aspect-ratio="1.7778"
style="position: relative; width: 8rem"
:class="$vuetify.theme.dark ? 'lighten-3' : 'darken-3'"
:style="{
borderRadius: $store.state.tweaks.roundThumb
? `${$store.state.tweaks.roundTweak / 3}rem`
: '0',
}"
>
</v-img>
<div
v-emoji
style="font-size: 0.75rem !important"
class="d-flex flex-column ml-2"
>
<b
class="text-left"
style="
{
height: 1.5rem;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
word-wrap: break-word;
white-space: normal;
}
"
>{{ video.title }}
</b>
<div
class="background--text caption mt-2 text-left d-inline-block text-truncate"
:class="$vuetify.theme.dark ? 'text--lighten-4' : 'text--darken-4'"
style="
{
height: 0.75rem;
}
"
>
{{ video.channel }}
</div>
</div>
</v-card>
<v-spacer></v-spacer>
<div class="d-flex flex-column">
<v-btn
text
tile
elevation="0"
class="flex-grow-1"
style="width: 2rem !important"
@click="deleted"
>
<v-icon>mdi-delete</v-icon>
</v-btn>
</div>
</v-card>
</template>
<script>
export default {
props: ["video"],
computed: {
thumbnail() {
return `https://img.youtube.com/vi/${this.video.id}/maxresdefault.jpg`;
},
},
methods: {
deleted() {
this.$emit("deleted");
},
},
};
</script>

27
NUXT/pages/history.vue Normal file
View File

@ -0,0 +1,27 @@
<template>
<div>
<history-card
v-for="(historyVideo, index) in historyVideos"
:key="index"
:video="historyVideo"
@deleted="deleteHistoryVideo(index)"
/>
</div>
</template>
<script>
import historyCard from "../components/historyCard.vue";
export default {
components: { historyCard },
computed: {
historyVideos() {
return this.$store.state.history.historyVideos;
},
},
methods: {
deleteHistoryVideo(target) {
this.$store.commit("history/removeHistory", target);
},
},
};
</script>

View File

@ -7,6 +7,26 @@
Local Playlists
</h4>
<playlist-card />
<v-btn
text
class="entry text-left setting-btn no-spacing"
to="/history"
nuxt
:style="{
borderRadius: `${$store.state.tweaks.roundTweak / 2}rem`,
paddingLeft:
$store.state.tweaks.roundTweak > 0 ? '' : '1.5rem !important',
}"
>
<v-icon
:style="{
borderRadius: `${$store.state.tweaks.roundTweak / 2}rem`,
}"
class=".icon"
>mdi-history</v-icon
>
History
</v-btn>
</div>
</template>
@ -16,3 +36,23 @@ export default {
components: { playlistCard },
};
</script>
<style scoped>
.setting-btn {
/* overrides Vuetify defaults (all caps) */
text-transform: none !important;
}
.setting-btn:first-letter {
/* Capitalizes first-letter only */
text-transform: uppercase !important;
}
.entry {
width: 100%;
font-size: 1.2em;
justify-content: left !important;
padding: 1.5em 0.5em 1.5em 0.5em !important;
}
.icon {
margin-right: 0.5em;
}
</style>

View File

@ -1,5 +1,5 @@
<template>
<div class="background" id="watch-body">
<div id="watch-body" class="background">
<div id="player-container">
<!-- // TODO: move component to default.vue -->
<!-- // TODO: pass sources through vuex instead of props -->
@ -158,7 +158,7 @@
<div class="avatar-link mr-3">
<v-img class="avatar-thumbnail" :src="video.channelImg" />
</div>
<div class="channel-byline" v-emoji>
<div v-emoji class="channel-byline">
<div class="channel-name" v-text="video.channelName" />
<div
class="caption background--text"
@ -350,6 +350,12 @@ export default {
this.recommends = result.renderedData.recommendations;
console.log("recommendations:", this.recommends);
// Store To History
this.$store.commit("history/addHistory", {
id: this.video.id,
title: this.video.title,
channel: this.video.channelName,
});
//--- API WatchTime call ---//
if (this.$store.state.watchTelemetry) {
this.playbackTracking = result.playbackTracking;

View File

@ -0,0 +1,38 @@
export const state = () => ({
historyVideos: [],
});
export const mutations = {
initHistory(state) {
if (process.client) {
// read local storage and parse the list of objects
state.historyVideos = localStorage
.getItem("historyVideos")
.split(",")
.map((video) => JSON.parse(video));
}
},
addHistory(state, video) {
state.historyVideos = state.historyVideos.filter((v) => v.id != video.id); // remove video if it is already in the history list
state.historyVideos.unshift(video);
localStorage.setItem(
"historyVideos",
state.historyVideos.map((video) => JSON.stringify(video))
);
},
removeHistory(state, index) {
state.historyVideos.splice(index, 1);
localStorage.setItem(
"historyVideos",
state.historyVideos.map((video) => JSON.stringify(video))
);
},
clearHistory(state) {
state.historyVideos = [];
localStorage.setItem(
"historyVideos",
state.historyVideos.map((video) => JSON.stringify(video))
);
},
};