mirror of
https://github.com/VueTubeApp/VueTube
synced 2024-11-26 05:05:23 +00:00
Merge branch 'working' of https://github.com/404-Program-not-found/VueTube into working
This commit is contained in:
commit
7322d830b5
11 changed files with 196 additions and 313 deletions
|
@ -1,130 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="content">
|
||||
<v-btn class="pausePlay" text @click="playing = !playing">
|
||||
<v-icon size="5em" color="white">mdi-{{ playing ? "pause" : "play" }}</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<div class="seekBar">
|
||||
<v-slider
|
||||
dense
|
||||
hide-details
|
||||
min="0"
|
||||
:max="videoEnd"
|
||||
:value="currentTime"
|
||||
@change="scrubTo()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<video
|
||||
ref="player"
|
||||
autoplay
|
||||
:src="vidSrc"
|
||||
width="100%"
|
||||
style="max-height: 50vh"
|
||||
@webkitfullscreenchange="handleFullscreenChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-for="(source, index) in sources" :key="index">
|
||||
{{ source.qualityLabel }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
sources: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//--- Basic Information ---//
|
||||
playerVersion: 0.1,
|
||||
vidSrc: null,
|
||||
|
||||
//--- Player State Information ---//
|
||||
playing: true,
|
||||
currentTime: 0,
|
||||
videoEnd: 0,
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
playing() {
|
||||
this.playing ? this.$refs.player.play() : this.$refs.player.pause();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const src = this.sources[this.sources.length - 1].url;
|
||||
this.vidSrc = src;
|
||||
|
||||
setInterval(this.updateTiming, 100);
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleFullscreenChange() {
|
||||
if (document.fullscreenElement === this.$refs.player) {
|
||||
this.$vuetube.statusBar.hide();
|
||||
this.$vuetube.navigationBar.hide();
|
||||
} else {
|
||||
this.$vuetube.statusBar.show();
|
||||
this.$vuetube.navigationBar.show();
|
||||
}
|
||||
},
|
||||
|
||||
scrubTo() {
|
||||
const player = this.$refs.player;
|
||||
player.currentTime = 0;
|
||||
console.log(val, this.currentTime, player.currentTime);
|
||||
},
|
||||
|
||||
updateTiming() {
|
||||
const player = this.$refs.player;
|
||||
if (player == undefined) return;
|
||||
this.videoEnd = player.duration;
|
||||
this.currentTime = player.currentTime;
|
||||
console.log(player.currentTime, this.currentTime);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/*** Overlay Information ***/
|
||||
.content {
|
||||
position: relative;
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.content video {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
.content:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/*** General Overlay Styling ***/
|
||||
.pausePlay {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.seekBar {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
47
NUXT/components/Player/controls.vue
Normal file
47
NUXT/components/Player/controls.vue
Normal file
|
@ -0,0 +1,47 @@
|
|||
<template>
|
||||
<div>
|
||||
|
||||
|
||||
<v-btn class="centerVideoControls" @click="togglePlaying()">
|
||||
<v-icon v-text="playing ? 'mdi-pause' : 'mdi-play' " ref="pausePlayIndicator" />
|
||||
</v-btn>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.centerVideoControls {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["video"],
|
||||
|
||||
data() {
|
||||
return {
|
||||
playing: true,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
togglePlaying() {
|
||||
if (this.video.paused) {
|
||||
this.video.play()
|
||||
this.playing = true;
|
||||
} else {
|
||||
this.video.pause()
|
||||
this.playing = false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
|
@ -1,75 +1,66 @@
|
|||
<template>
|
||||
<div>
|
||||
<div @click="toggleControls()" class="content">
|
||||
<div style="position: relative;">
|
||||
<video
|
||||
ref="player"
|
||||
autoplay
|
||||
:src="vidSrc"
|
||||
width="100%"
|
||||
style="max-height: 50vh; display: block"
|
||||
@webkitfullscreenchange="handleFullscreenChange"
|
||||
/>
|
||||
<seekbar :video=$refs.player v-if="$refs.player" />
|
||||
|
||||
|
||||
|
||||
<!-- Video Controls -->
|
||||
<div class="videoControls" v-if="$refs.player">
|
||||
<div class="videoControlsWrap">
|
||||
|
||||
|
||||
<controls :video=$refs.player />
|
||||
|
||||
<div v-show="showControls" class="controls">
|
||||
<v-btn class="pausePlay" text @click="playing = !playing">
|
||||
<v-icon size="5em" color="white">mdi-{{ playing ? "pause" : "play" }}</v-icon>
|
||||
</v-btn>
|
||||
|
||||
<scrubber class="scrubber" :duration="duration" :endDuration="endDuration" />
|
||||
</div>
|
||||
|
||||
<video
|
||||
ref="player"
|
||||
:src="vidSrc"
|
||||
width="100%"
|
||||
style="max-height: 50vh"
|
||||
@webkitfullscreenchange="handleFullscreenChange"
|
||||
/>
|
||||
</div>
|
||||
<!-- End Video Controls -->
|
||||
|
||||
<div v-for="(source, index) in sources" :key="index">
|
||||
{{ source.qualityLabel }}
|
||||
</div>
|
||||
|
||||
<!-- <v-slider v-model="value" step="0"></v-slider> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.videoControls {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
}
|
||||
.videoControlsWrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import scrubber from "./scrubber.vue";
|
||||
import seekbar from '~/components/Player/seekbar.vue';
|
||||
import controls from '~/components/Player/controls.vue';
|
||||
|
||||
export default {
|
||||
props: ["sources"],
|
||||
components: {
|
||||
scrubber,
|
||||
},
|
||||
props: {
|
||||
sources: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
seekbar,
|
||||
controls
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//--- Basic Information ---//
|
||||
playerVersion: 0.1,
|
||||
vidSrc: null,
|
||||
|
||||
//--- Player State Information ---//
|
||||
showControls: false,
|
||||
playing: false,
|
||||
duration: 0,
|
||||
endDuration: 0,
|
||||
vidSrc: "",
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
playing() {
|
||||
console.log("Changed Playback State");
|
||||
this.playing ? this.$refs.player.play() : this.$refs.player.pause();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
const src = this.sources[this.sources.length - 1].url;
|
||||
this.vidSrc = src;
|
||||
|
||||
console.log("Beta Player Sources Debug:", this.sources, src);
|
||||
|
||||
setTimeout(function() { this.$refs.player.play(); }, 1000); // Auto Play
|
||||
|
||||
setInterval(this.updateTiming, 100); // Auto Update Scrubber
|
||||
this.vidSrc = this.sources[this.sources.length-1].url;
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleFullscreenChange() {
|
||||
if (document.fullscreenElement === this.$refs.player) {
|
||||
|
@ -81,57 +72,9 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
updateTiming() {
|
||||
const player = this.$refs.player;
|
||||
if (player == undefined) return;
|
||||
this.duration = player.currentTime;
|
||||
this.endDuration = player.duration;
|
||||
getPlayer() {
|
||||
return this.$refs.player;
|
||||
},
|
||||
|
||||
toggleControls() {
|
||||
this.showControls = !this.showControls;
|
||||
}
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/*** Overlay Information ***/
|
||||
.content {
|
||||
position: relative;
|
||||
width: 500px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.content video {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
.content:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/*** General Overlay Styling ***/
|
||||
.controls {
|
||||
z-index: 999;
|
||||
}
|
||||
.pausePlay {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
height: 5em !important;
|
||||
width: 5em !important;
|
||||
}
|
||||
.scrubber {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
|
|
@ -9,16 +9,6 @@
|
|||
style="max-height: 50vh; display: block"
|
||||
@webkitfullscreenchange="handleFullscreenChange"
|
||||
/>
|
||||
<v-progress-linear
|
||||
active
|
||||
background-color="primary"
|
||||
background-opacity="0.5"
|
||||
:buffer-value="buffered"
|
||||
color="primary"
|
||||
height="3"
|
||||
query
|
||||
:value="percentage"
|
||||
/>
|
||||
<!-- <v-slider v-model="value" step="0"></v-slider> -->
|
||||
</div>
|
||||
</template>
|
||||
|
@ -26,21 +16,6 @@
|
|||
<script>
|
||||
export default {
|
||||
props: ["vidSrc"],
|
||||
data() {
|
||||
return {
|
||||
percentage: 0,
|
||||
buffered: 0,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
let vid = this.$refs.player;
|
||||
vid.ontimeupdate = () => {
|
||||
this.percentage = (vid.currentTime / vid.duration) * 100;
|
||||
};
|
||||
vid.addEventListener("progress", () => {
|
||||
this.buffered = (vid.buffered.end(0) / vid.duration) * 100;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
handleFullscreenChange() {
|
||||
if (document.fullscreenElement === this.$refs.player) {
|
|
@ -1,44 +0,0 @@
|
|||
<template>
|
||||
<div class="scrubber">
|
||||
<div id="progress" class="primary" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
endDuration: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
percentage: 0,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const vm = this;
|
||||
setInterval(function () {
|
||||
vm.percentage = (vm.duration / vm.endDuration) * 100;
|
||||
|
||||
document.getElementById("progress").style.width = vm.percentage + "%";
|
||||
}, 100);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.scrubber {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
#progress {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
42
NUXT/components/Player/seekbar.vue
Normal file
42
NUXT/components/Player/seekbar.vue
Normal file
|
@ -0,0 +1,42 @@
|
|||
<template>
|
||||
<div>
|
||||
|
||||
|
||||
<v-progress-linear
|
||||
active
|
||||
background-color="primary"
|
||||
background-opacity="0.5"
|
||||
:buffer-value="buffered"
|
||||
color="primary"
|
||||
height="3"
|
||||
query
|
||||
:value="percentage"
|
||||
/>
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ["video"],
|
||||
|
||||
data() {
|
||||
return {
|
||||
percentage: 0,
|
||||
buffered: 0
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.video.ontimeupdate = () => {
|
||||
this.percentage = (this.video.currentTime / this.video.duration) * 100;
|
||||
};
|
||||
this.video.addEventListener("progress", () => {
|
||||
this.buffered = (this.video.buffered.end(0) / this.video.duration) * 100;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
|
@ -93,20 +93,19 @@ export default {
|
|||
},
|
||||
|
||||
mounted() {
|
||||
this.$vuetube.resetBackActions();
|
||||
//--- Back Button Listener ---//
|
||||
this.backHandler = CapacitorApp.addListener(
|
||||
"backButton",
|
||||
({ canGoBack }) => {
|
||||
//--- Back Closes Search ---//
|
||||
if (this.search) {
|
||||
this.search = false;
|
||||
this.$vuetube.back
|
||||
);
|
||||
|
||||
//--- Back Goes Back ---//
|
||||
} else if (!canGoBack) {
|
||||
CapacitorApp.exitApp();
|
||||
} else {
|
||||
window.history.back();
|
||||
}
|
||||
this.$vuetube.addBackAction(
|
||||
() => {
|
||||
this.search = false;
|
||||
},
|
||||
() => {
|
||||
return this.search;
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
/>
|
||||
|
||||
<!-- Stock Player -->
|
||||
<videoPlayer
|
||||
<legacyPlayer
|
||||
id="player"
|
||||
ref="player"
|
||||
v-touch="{ down: () => $router.push('/home') }"
|
||||
|
@ -209,6 +209,7 @@ import VidLoadRenderer from "~/components/vidLoadRenderer.vue";
|
|||
import { getCpn } from "~/plugins/utils";
|
||||
import SlimVideoDescriptionRenderer from "~/components/UtilRenderers/slimVideoDescriptionRenderer.vue";
|
||||
import ItemSectionRenderer from "~/components/SectionRenderers/itemSectionRenderer.vue";
|
||||
import legacyPlayer from "~/components/Player/legacy.vue";
|
||||
import vuetubePlayer from "~/components/Player/index.vue";
|
||||
import ShelfRenderer from "~/components/SectionRenderers/shelfRenderer.vue";
|
||||
import mainCommentRenderer from "~/components/Comments/mainCommentRenderer.vue";
|
||||
|
@ -222,6 +223,7 @@ export default {
|
|||
VidLoadRenderer,
|
||||
SlimVideoDescriptionRenderer,
|
||||
vuetubePlayer,
|
||||
legacyPlayer,
|
||||
ItemSectionRenderer,
|
||||
SwipeableBottomSheet,
|
||||
mainCommentRenderer,
|
||||
|
@ -258,6 +260,7 @@ export default {
|
|||
mounted() {
|
||||
this.mountedInit();
|
||||
|
||||
this.$vuetube.resetBackActions();
|
||||
this.backHandler = CapacitorApp.addListener(
|
||||
"backButton",
|
||||
({ canGoBack }) => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="accent">
|
||||
<div>
|
||||
|
||||
<player :sources="sources" v-if="sources.length > 0" />
|
||||
|
||||
|
|
26
NUXT/plugins/classes/backHander.js
Normal file
26
NUXT/plugins/classes/backHander.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { App as CapacitorApp } from "@capacitor/app";
|
||||
export default class backHandler {
|
||||
constructor() {
|
||||
this.backStack = []
|
||||
}
|
||||
|
||||
back({ canGoBack }) {
|
||||
if (this.backStack.length > 0) {
|
||||
let lastResult = false
|
||||
while (!lastResult && this.backStack.length > 0) {
|
||||
const backAction = this.backStack.pop()
|
||||
lastResult = backAction()
|
||||
}
|
||||
if (lastResult) return
|
||||
}
|
||||
if (!canGoBack) {
|
||||
CapacitorApp.exitApp();
|
||||
} else {
|
||||
window.history.back();
|
||||
}
|
||||
}
|
||||
|
||||
addAction(callback) {
|
||||
this.backStack.push(callback)
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import constants from "./constants";
|
|||
import { hexToRgb, rgbToHex, parseEmoji } from "./utils";
|
||||
import { Haptics, ImpactStyle } from "@capacitor/haptics";
|
||||
import Vue from "vue";
|
||||
import backHandler from "./classes/backHander";
|
||||
|
||||
Vue.directive("emoji", {
|
||||
inserted: function (el) {
|
||||
|
@ -14,6 +15,8 @@ Vue.directive("emoji", {
|
|||
},
|
||||
});
|
||||
|
||||
let backActions = new backHandler();
|
||||
|
||||
const module = {
|
||||
//--- Get GitHub Commits ---//
|
||||
commits: new Promise((resolve, reject) => {
|
||||
|
@ -109,6 +112,25 @@ const module = {
|
|||
rgbToHex(r, g, b) {
|
||||
return rgbToHex(r, g, b);
|
||||
},
|
||||
|
||||
resetBackActions() {
|
||||
backActions = new backHandler();
|
||||
},
|
||||
|
||||
addBackAction(callback, condition = true) {
|
||||
backActions.addAction(() => {
|
||||
if (condition) {
|
||||
callback();
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
back(listenerFunc) {
|
||||
backActions.back(listenerFunc);
|
||||
}
|
||||
};
|
||||
|
||||
//--- Start ---//
|
||||
|
|
Loading…
Reference in a new issue