mirror of https://github.com/VueTubeApp/VueTube
feat: added local history (#609)
This commit is contained in:
parent
405531a03b
commit
f7ce9a62ea
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
);
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue