mirror of
https://github.com/VueTubeApp/VueTube
synced 2025-01-06 23:51:13 +00:00
commit
f95f503170
12 changed files with 169 additions and 59 deletions
|
@ -420,10 +420,16 @@ export default {
|
|||
this.vid = this.$refs.player;
|
||||
|
||||
// TODO: this.$store.state.player.quality, check if exists and select the closest one
|
||||
if (this.$store.state.player.preload) this.prebuffer(this.sources[5].url);
|
||||
|
||||
if (this.$store.state.player.preload) this.prebuffer(this.sources[0].url);
|
||||
else {
|
||||
this.audSrc = this.sources[this.sources.length - 1].url;
|
||||
this.vidSrc = this.sources[5].url;
|
||||
this.prebuffer(this.sources[0].url);
|
||||
this.sources.forEach((source) => {
|
||||
if (source.mimeType.indexOf("audio") > -1) {
|
||||
this.audSrc = source.url;
|
||||
this.vidSrc = this.sources[0].url;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.$youtube.getSponsorBlock(this.video.id, (data) => {
|
||||
|
@ -463,9 +469,9 @@ export default {
|
|||
// // There is not enough data to keep playing from this point
|
||||
// }
|
||||
if (this.vid.readyState >= 3) {
|
||||
this.$refs.audio.play();
|
||||
this.bufferingDetected = false;
|
||||
this.$refs.audio.currentTime = this.vid.currentTime;
|
||||
this.$refs.audio.play();
|
||||
|
||||
if (!this.isMusic) {
|
||||
this.$refs.audio.playbackRate = this.$store.state.player.speed;
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
video: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
video: {},
|
||||
buffering: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
|
|
|
@ -38,10 +38,7 @@ export default {
|
|||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
controls: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
controls: {},
|
||||
buffered: {
|
||||
type: Number,
|
||||
required: true,
|
||||
|
|
|
@ -7,7 +7,14 @@
|
|||
scrollable
|
||||
>
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn fab text small color="white" v-bind="attrs" v-on="on">
|
||||
<v-btn
|
||||
fab
|
||||
text
|
||||
small
|
||||
color="white"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
>
|
||||
{{
|
||||
sources.find((src) => src.url == currentSource.src).qualityLabel
|
||||
? sources.find((src) => src.url == currentSource.src).qualityLabel
|
||||
|
@ -29,7 +36,7 @@
|
|||
</v-subheader>
|
||||
<v-divider />
|
||||
<v-card-text
|
||||
style="max-height: 50vh"
|
||||
style="max-height: 50vh; flex-direction: column !important"
|
||||
class="pa-0 d-flex flex-column-reverse"
|
||||
>
|
||||
<v-list-item
|
||||
|
@ -58,7 +65,7 @@
|
|||
<v-list-item-title>
|
||||
{{ src.qualityLabel ? src.qualityLabel : "" }} ({{
|
||||
src.quality
|
||||
}}) {{ src.bitrate }}bps
|
||||
}}) {{ (src.bitrate / 1000000).toFixed(2) }}Mbps
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle>
|
||||
{{ src.mimeType }} {{ src.averageBitrate }}
|
||||
|
@ -72,12 +79,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
props: {
|
||||
currentSource: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
currentSource: {},
|
||||
sources: {
|
||||
type: Array,
|
||||
required: true,
|
||||
|
|
|
@ -58,14 +58,8 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
video: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
controls: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
video: {},
|
||||
controls: {},
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
|
@ -74,10 +68,7 @@ export default {
|
|||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
currentTime: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
currentTime: {},
|
||||
duration: {
|
||||
type: Number,
|
||||
required: true,
|
||||
|
|
|
@ -44,10 +44,7 @@ export default {
|
|||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
controls: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
controls: {},
|
||||
},
|
||||
data: () => ({
|
||||
colors: {
|
||||
|
|
|
@ -12,14 +12,8 @@ export default {
|
|||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
currentTime: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
controls: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
currentTime: {},
|
||||
controls: {},
|
||||
},
|
||||
computed: {
|
||||
humanDuration() {
|
||||
|
|
108
NUXT/components/UtilRenderers/YtTextFormatterNew.vue
Normal file
108
NUXT/components/UtilRenderers/YtTextFormatterNew.vue
Normal file
|
@ -0,0 +1,108 @@
|
|||
<template>
|
||||
<div class="yt-text-formatter">
|
||||
<p v-html="formatTitle">
|
||||
{{ textRuns.content }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
textRuns: {},
|
||||
},
|
||||
emits: ["play", "pause"],
|
||||
data: () => ({
|
||||
paused: false,
|
||||
}),
|
||||
computed: {
|
||||
formatTitle() {
|
||||
let tempContent = "";
|
||||
let img =
|
||||
"<img src = 'https://www.gstatic.com/youtube/img/watch/yt_favicon.png' style=\"height: 10px; width: 14px;\"/>";
|
||||
if (this.textRuns.content && this.textRuns.commandRuns) {
|
||||
tempContent = this.textRuns.content;
|
||||
let arrayWithIndexes = [];
|
||||
let arrayWithReplaceParts = [];
|
||||
this.textRuns.commandRuns.forEach((commandRun) => {
|
||||
arrayWithIndexes.push([commandRun.startIndex, commandRun.length]);
|
||||
//[textToReplace, urlFromEndpoint]
|
||||
if (commandRun.onTap.innertubeCommand.commandMetadata) {
|
||||
arrayWithReplaceParts.push([
|
||||
this.textRuns.content.substring(
|
||||
commandRun.startIndex,
|
||||
commandRun.startIndex + commandRun.length
|
||||
),
|
||||
commandRun.onTap.innertubeCommand.commandMetadata
|
||||
.webCommandMetadata.url,
|
||||
]);
|
||||
} else if (commandRun.onTap.innertubeCommand.urlEndpoint) {
|
||||
arrayWithReplaceParts.push([
|
||||
this.textRuns.content.substring(
|
||||
commandRun.startIndex,
|
||||
commandRun.startIndex + commandRun.length
|
||||
),
|
||||
commandRun.onTap.innertubeCommand.urlEndpoint.url,
|
||||
]);
|
||||
}
|
||||
});
|
||||
console.log(arrayWithIndexes);
|
||||
console.log(arrayWithReplaceParts);
|
||||
|
||||
arrayWithReplaceParts.forEach((text) => {
|
||||
if (text[1].indexOf("/hashtag/") > -1) {
|
||||
//skip
|
||||
} else if (text[1].indexOf("watch?v=") > -1) {
|
||||
let nameOfUrl = text[0].replace(/ •/, " •");
|
||||
let newUrl =
|
||||
"<a" +
|
||||
' onclick=openInternal("' +
|
||||
text[1] +
|
||||
'") style="background-color: rgba(0,0,0,0.051); border-radius: 8px; white-space: nowrap;">' +
|
||||
img +
|
||||
nameOfUrl +
|
||||
"</a>";
|
||||
tempContent = tempContent.replace(text[0], newUrl);
|
||||
} else if (text[1].indexOf("/channel/") > -1) {
|
||||
let nameOfUrl = text[0].replace(/ /, " ");
|
||||
// let newUrl =
|
||||
// "<a" + ' onclick=openInternal("' + text[1] + '") style="background-color: rgba(0,0,0,0.051); border-radius: 8px; white-space: nowrap;">' + img + nameOfUrl + "</a>";
|
||||
|
||||
// Temporary
|
||||
let newUrl =
|
||||
"<a" +
|
||||
' onclick=openInternal("channel") style="background-color: rgba(0,0,0,0.051); border-radius: 8px; white-space: nowrap;">' +
|
||||
img +
|
||||
nameOfUrl +
|
||||
"</a>";
|
||||
tempContent = tempContent.replace(text[0], newUrl);
|
||||
} else {
|
||||
let params = new Proxy(new URLSearchParams(text[1]), {
|
||||
get: (searchParams, prop) => searchParams.get(prop),
|
||||
});
|
||||
let url = decodeURI(params.q);
|
||||
let newUrl =
|
||||
"<a" + ' onclick=openExternal("' + url + '")>' + text[0] + "</a>";
|
||||
tempContent = tempContent.replace(text[0], newUrl);
|
||||
}
|
||||
});
|
||||
}
|
||||
console.log(tempContent);
|
||||
return tempContent;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
window.openExternal = this.openExternal;
|
||||
window.openInternal = this.openInternal;
|
||||
},
|
||||
methods: {
|
||||
openExternal(url) {
|
||||
console.log(url);
|
||||
this.$vuetube.openExternal(url);
|
||||
},
|
||||
async openInternal(url) {
|
||||
await this.$router.push(url);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -1,25 +1,24 @@
|
|||
<template>
|
||||
<div class="description" v-if="render.descriptionBodyText">
|
||||
<yt-text-formatter :textRuns="render.descriptionBodyText.runs">
|
||||
<div v-if="render.attributedDescriptionBodyText.content" class="description">
|
||||
<yt-text-formatter :text-runs="render.attributedDescriptionBodyText">
|
||||
</yt-text-formatter>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import YtTextFormatter from "~/components/UtilRenderers/YtTextFormatterNew.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
YtTextFormatter,
|
||||
},
|
||||
props: ["render"],
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.description {
|
||||
white-space: pre-line;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import YtTextFormatter from "~/components/UtilRenderers/YtTextFormatter.vue";
|
||||
|
||||
export default {
|
||||
props: ["render"],
|
||||
|
||||
components: {
|
||||
YtTextFormatter,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -75,3 +75,8 @@ export default {
|
|||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
a {
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -16,6 +16,7 @@ class Innertube {
|
|||
constructor(ErrorCallback) {
|
||||
this.ErrorCallback = ErrorCallback || undefined;
|
||||
this.retry_count = 0;
|
||||
this.playerParams = "";
|
||||
}
|
||||
|
||||
checkErrorCallback() {
|
||||
|
@ -191,13 +192,14 @@ class Innertube {
|
|||
data: {
|
||||
...data,
|
||||
...{
|
||||
playerParams: this.playerParams,
|
||||
contentCheckOk: false,
|
||||
mwebCapabilities: {
|
||||
mobileClientSupportsLivestream: true,
|
||||
},
|
||||
playbackContext: {
|
||||
contentPlaybackContext: {
|
||||
currentUrl: "/watch?v=" + id,
|
||||
currentUrl: "/watch?v=" + id + "&pp=" + this.playerParams,
|
||||
vis: 0,
|
||||
splay: false,
|
||||
autoCaptionsDefaultOn: false,
|
||||
|
@ -370,6 +372,12 @@ class Innertube {
|
|||
const ownerData = vidMetadata.contents.find(
|
||||
(content) => content.slimOwnerRenderer
|
||||
)?.slimOwnerRenderer;
|
||||
|
||||
try {
|
||||
console.log(vidMetadata.contents);
|
||||
this.playerParams =
|
||||
ownerData.navigationEndpoint.watchEndpoint.playerParams;
|
||||
} catch (e) {}
|
||||
const vidData = {
|
||||
id: details.videoId,
|
||||
title: details.title,
|
||||
|
|
|
@ -14,7 +14,10 @@ export const state = () => ({
|
|||
export const mutations = {
|
||||
initPlayer(state) {
|
||||
if (process.client) {
|
||||
state.loop = JSON.parse(localStorage.getItem("loop")) === true; // defaults to false
|
||||
state.loop =
|
||||
localStorage.getItem("loop") !== "undefined"
|
||||
? JSON.parse(localStorage.getItem("loop"))
|
||||
: true; // defaults to false
|
||||
state.speed = JSON.parse(localStorage.getItem("speed")) || 1; // defaults to 1
|
||||
state.speedAutosave = !(
|
||||
// false if false, defaults to true
|
||||
|
|
Loading…
Reference in a new issue