VueTube/NUXT/pages/watch.vue

275 lines
8.1 KiB
Vue
Raw Normal View History

2022-02-24 22:29:34 +00:00
<template>
2022-03-25 19:21:00 +00:00
<div class="background">
<!-- Stock Player -->
<videoPlayer
style="position: sticky; top: 0; z-index: 696969"
:vid-src="vidSrc"
ref="player"
/>
<!-- VueTube Player V1 -->
<!-- <VTPlayerV1 :sources="sources" v-if="sources.length > 0" />-->
2022-03-25 19:21:00 +00:00
<v-card v-if="loaded" class="ml-2 mr-2 background" flat>
<v-card-title
class="mt-2"
style="
padding-top: 0;
padding-bottom: 0;
font-size: 0.95rem;
line-height: 1rem;
"
2022-03-21 00:30:59 +00:00
v-text="title"
/>
<v-card-text>
<div style="margin-bottom: 1rem">
{{ views }} views {{ uploaded }}
</div>
<!-- Scrolling Div For Interactions --->
2022-03-21 00:30:59 +00:00
<div style="display: flex; margin-bottom: 1em">
<v-list-item
v-for="(item, index) in interactions"
:key="index"
style="padding: 0; flex: 0 0 20%"
>
<v-btn
text
class="vertical-button"
style="padding: 0; margin: 0"
elevation="0"
:disabled="item.disabled"
2022-03-22 05:47:28 +00:00
@click="callMethodByName(item.actionName)"
>
<v-icon v-text="item.icon" />
<div
class="mt-2"
style="font-size: 0.66rem"
v-text="item.value || item.name"
/>
</v-btn>
</v-list-item>
<v-spacer />
2022-03-20 18:42:12 +00:00
<v-btn text @click="showMore = !showMore">
<v-icon v-if="showMore">mdi-chevron-up</v-icon>
<v-icon v-else>mdi-chevron-down</v-icon>
</v-btn>
</div>
<!-- End Scrolling Div For Interactions --->
2022-03-22 01:13:48 +00:00
<!-- <hr /> -->
2022-03-20 16:55:25 +00:00
<p>Channel Stuff</p>
</v-card-text>
2022-03-21 23:47:11 +00:00
<div v-if="showMore" class="scroll-y ml-2 mr-2">
<slim-video-description-renderer :render="description" />
2022-03-21 00:30:59 +00:00
</div>
<!-- <v-bottom-sheet
2022-03-21 13:21:18 +00:00
v-model="showMore"
2022-03-25 19:21:00 +00:00
color="background"
2022-03-21 13:21:18 +00:00
style="z-index: 9999999"
>
<v-sheet style="padding: 1em">
<v-btn block @click="showMore = !showMore"
><v-icon>mdi-chevron-down</v-icon></v-btn
><br />
<div class="scroll-y">
{{ description }}
</div>
2022-03-20 18:42:12 +00:00
</v-sheet>
</v-bottom-sheet> -->
2022-03-25 19:21:00 +00:00
<!-- <v-bottom-sheet v-model="share" color="background" style="z-index: 9999999">
2022-03-21 00:30:59 +00:00
<v-sheet style="padding: 1em">
2022-03-20 18:42:12 +00:00
<div class="scroll-y">
{{ description }}
</div>
</v-sheet>
2022-03-21 13:21:18 +00:00
</v-bottom-sheet> -->
2022-03-19 06:18:07 +00:00
</v-card>
2022-03-24 11:47:13 +00:00
<vid-load-renderer v-if="!recommends" />
<shelf-renderer v-else :render="recommends" />
2022-02-24 22:29:34 +00:00
</div>
</template>
<script>
2022-03-22 05:47:28 +00:00
import { Share } from "@capacitor/share";
2022-03-24 20:46:17 +00:00
import ShelfRenderer from "~/components/SectionRenderers/shelfRenderer.vue";
import VidLoadRenderer from "~/components/vidLoadRenderer.vue";
import { getCpn } from "~/plugins/utils";
import SlimVideoDescriptionRenderer from "~/components/UtilRenderers/slimVideoDescriptionRenderer.vue";
2022-03-22 05:47:28 +00:00
2022-02-24 22:29:34 +00:00
export default {
2022-03-27 04:31:32 +00:00
components: { ShelfRenderer, VidLoadRenderer, SlimVideoDescriptionRenderer },
2022-02-24 22:29:34 +00:00
data() {
return {
interactions: [
2022-03-21 00:30:59 +00:00
{
name: "Likes",
2022-03-22 01:13:48 +00:00
icon: "mdi-thumb-up-outline",
2022-03-22 05:47:28 +00:00
// action: null,
2022-03-21 00:30:59 +00:00
value: this.likes,
disabled: true,
},
{
name: "Dislikes",
2022-03-22 01:13:48 +00:00
icon: "mdi-thumb-down-outline",
2022-03-22 05:47:28 +00:00
// action: this.dislike(),
actionName: "dislike",
2022-03-21 00:30:59 +00:00
value: this.dislikes,
disabled: true,
},
{
name: "Share",
2022-03-22 01:13:48 +00:00
icon: "mdi-share-outline",
2022-03-22 05:47:28 +00:00
// action: this.share(),
actionName: "share",
disabled: false,
2022-03-21 00:30:59 +00:00
},
],
showMore: false,
2022-03-22 05:47:28 +00:00
// share: false,
title: null,
uploaded: null,
vidSrc: null,
sources: [],
description: null,
views: null,
2022-03-24 11:47:13 +00:00
recommends: null,
loaded: false,
interval: null,
};
2022-03-13 23:21:41 +00:00
},
2022-03-25 03:25:51 +00:00
watch: {
// Watch for change in the route query string (in this case, ?v=xxxxxxxx to ?v=yyyyyyyy)
$route: {
deep: true,
handler(newRt, oldRt) {
if (newRt.query.v != oldRt.query.v) {
// Exit fullscreen if currently in fullscreen
// if (this.$refs.player) this.$refs.player.webkitExitFullscreen();
2022-03-25 03:25:51 +00:00
// Reset player and run getVideo function again
this.vidSrc = "";
this.startTime = Math.floor(Date.now() / 1000);
clearInterval(this.interval);
2022-03-25 03:25:51 +00:00
this.getVideo();
}
},
},
},
2022-03-13 23:21:41 +00:00
mounted() {
this.startTime = Math.floor(Date.now() / 1000);
this.getVideo();
},
destroyed() {
clearInterval(this.interval);
},
methods: {
getVideo() {
this.likes = 100;
this.loaded = false;
this.$youtube.getVid(this.$route.query.v).then((result) => {
console.log("Video info data", result);
console.log(result.availableResolutions);
//--- VueTube Player v1 ---//
this.sources = result.availableResolutions;
//--- Legacy Player ---//
this.vidSrc =
result.availableResolutions[
result.availableResolutions.length - 1
].url; // Takes the highest available resolution with both video and Audio. Note this will be lower than the actual highest resolution
//--- Content Stuff ---//
this.title = result.title;
2022-03-27 04:31:32 +00:00
this.description = result.renderedData.description; // While this works, I do recommend using the rendered description instead in the future as there are some things a pure string wouldn't work with
this.views = parseInt(result.metadata.viewCount).toLocaleString();
this.likes = result.metadata.likes.toLocaleString();
this.uploaded = result.metadata.uploadDate;
this.interactions[0].value = result.metadata.likes.toLocaleString();
this.loaded = true;
2022-03-21 00:27:41 +00:00
this.recommends = result.renderedData.recommendations;
// .catch((error) => this.$logger("Watch", error, true));
console.log("recommendations:", this.recommends);
//--- API WatchTime call ---//
this.playbackTracking = result.playbackTracking;
this.st = 0;
this.cpn = getCpn();
this.initWatchTime().then(() => {
this.sendWatchTime();
this.interval = setInterval(this.sendWatchTime, 30000);
});
});
2022-03-19 06:18:07 +00:00
this.$youtube.getReturnYoutubeDislike(this.$route.query.v, (data) => {
this.dislikes = data.dislikes.toLocaleString();
this.interactions[1].value = data.dislikes.toLocaleString();
});
},
2022-03-22 05:47:28 +00:00
callMethodByName(name) {
// Helper function needed because of issues when directly calling method
// using item.action in the v-for loop
this[name]();
},
2022-03-21 23:47:11 +00:00
dislike() {},
2022-03-22 05:47:28 +00:00
async share() {
// this.share = !this.share;
await Share.share({
title: this.title,
text: this.title,
url: "https://youtu.be/" + this.$route.query.v,
dialogTitle: "Share video",
2022-03-22 05:47:28 +00:00
});
},
sendWatchTime() {
const player = this.$refs.player.getPlayer();
const rt = Math.floor(Date.now() / 1000) - this.startTime;
const params = {
cpn: this.cpn,
rt: rt,
rti: rt,
rtn: rt,
cmt: player.currentTime,
et: player.currentTime,
st: this.st,
state: player.paused ? "paused" : "playing",
volume: 100,
muted: 0,
fmt: 396,
};
this.st = player.currentTime;
this.$youtube.saveApiStats(
params,
this.playbackTracking.videostatsWatchtimeUrl.baseUrl
);
},
async initWatchTime() {
await this.$youtube.saveApiStats(
{
cpn: this.cpn,
fmt: 243,
rtn: Math.floor(Date.now() / 1000) - this.startTime,
rt: Math.floor(Date.now() / 1000) - this.startTime,
fmt: 243,
muted: 0,
},
this.playbackTracking.videostatsPlaybackUrl.baseUrl
);
},
2022-03-21 23:47:11 +00:00
},
};
2022-02-24 22:29:34 +00:00
</script>
<style>
.vertical-button span.v-btn__content {
flex-direction: column;
justify-content: space-around;
}
</style>