mirror of
https://github.com/TeamPiped/Piped.git
synced 2024-11-28 08:27:27 +00:00
Preferences + Format code.
This commit is contained in:
parent
e853cb9840
commit
4891c57bbd
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,7 +2,6 @@
|
|||||||
node_modules
|
node_modules
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env.local
|
.env.local
|
||||||
.env.*.local
|
.env.*.local
|
||||||
|
@ -1,24 +1,29 @@
|
|||||||
# piped
|
# piped
|
||||||
|
|
||||||
## Project setup
|
## Project setup
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compiles and hot-reloads for development
|
### Compiles and hot-reloads for development
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run serve
|
npm run serve
|
||||||
```
|
```
|
||||||
|
|
||||||
### Compiles and minifies for production
|
### Compiles and minifies for production
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Lints and fixes files
|
### Lints and fixes files
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run lint
|
npm run lint
|
||||||
```
|
```
|
||||||
|
|
||||||
### Customize configuration
|
### Customize configuration
|
||||||
|
|
||||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||||
|
54
src/App.vue
54
src/App.vue
@ -1,33 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="uk-container uk-container-expand uk-light uk-height-viewport" style="background:#0b0e0f">
|
<div
|
||||||
<nav class="uk-navbar-container uk-container-expand uk-light" style="background:#0b0e0f" uk-navbar>
|
class="uk-container uk-container-expand uk-light uk-height-viewport"
|
||||||
<div class="uk-navbar-left">
|
style="background: #0b0e0f"
|
||||||
<router-link class="uk-navbar-item uk-logo uk-text-bold" to="/">Piped</router-link>
|
>
|
||||||
</div>
|
<nav
|
||||||
<div class="uk-navbar-right">
|
class="uk-navbar-container uk-container-expand uk-light"
|
||||||
<ul class="uk-navbar-nav">
|
style="background: #0b0e0f"
|
||||||
<li>
|
uk-navbar
|
||||||
<router-link to="/login">Login</router-link>
|
>
|
||||||
</li>
|
<div class="uk-navbar-left">
|
||||||
<li>
|
<router-link class="uk-navbar-item uk-logo uk-text-bold" to="/"
|
||||||
<router-link to="/feed">Feed</router-link>
|
>Piped</router-link
|
||||||
</li>
|
>
|
||||||
</ul>
|
</div>
|
||||||
</div>
|
<div class="uk-navbar-right">
|
||||||
</nav>
|
<ul class="uk-navbar-nav">
|
||||||
|
<li>
|
||||||
|
<router-link to="/preferences">Preferences</router-link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<router-link to="/login">Login</router-link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<router-link to="/feed">Feed</router-link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
<router-view />
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {};
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
export default {
|
export default {
|
||||||
BASE_URL: 'https://pipedapi.kavin.rocks',
|
BASE_URL: localStorage.getItem("instance") || 'https://pipedapi.kavin.rocks',
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,32 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="channel">
|
<div v-if="channel">
|
||||||
<h1 class="uk-text-center"><img v-bind:src="channel.avatarUrl">{{ channel.name }}</h1>
|
<h1 class="uk-text-center">
|
||||||
<img v-bind:src="channel.bannerUrl" style="width: 100%">
|
<img v-bind:src="channel.avatarUrl" />{{ channel.name }}
|
||||||
<p v-html="this.channel.description.replaceAll('\n', '<br>')"></p>
|
</h1>
|
||||||
|
<img v-bind:src="channel.bannerUrl" style="width: 100%" />
|
||||||
|
<p v-html="this.channel.description.replaceAll('\n', '<br>')"></p>
|
||||||
|
|
||||||
<hr>
|
<hr />
|
||||||
|
|
||||||
<div class="uk-grid-small" style="width: 100%" uk-grid="parallax: 0">
|
<div class="uk-grid-small" style="width: 100%" uk-grid="parallax: 0">
|
||||||
<div style="width: 288px" v-bind:key="item.url" v-for="item in this.channel.relatedStreams">
|
<div
|
||||||
<router-link class="uk-link-muted" style="height: 100px" v-bind:to="item.url || '/'">
|
style="width: 288px"
|
||||||
<img style="width: 100%" v-bind:src="item.thumbnail">
|
v-bind:key="item.url"
|
||||||
<a>{{ item.title }}</a>
|
v-for="item in this.channel.relatedStreams"
|
||||||
</router-link>
|
>
|
||||||
<br>
|
<router-link
|
||||||
<a>{{ timeFormat(item.duration) }}</a>
|
class="uk-link-muted"
|
||||||
|
style="height: 100px"
|
||||||
|
v-bind:to="item.url || '/'"
|
||||||
|
>
|
||||||
|
<img style="width: 100%" v-bind:src="item.thumbnail" />
|
||||||
|
<a>{{ item.title }}</a>
|
||||||
|
</router-link>
|
||||||
|
<br />
|
||||||
|
<a>{{ timeFormat(item.duration) }}</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -25,27 +35,31 @@ import Constants from "@/Constants.js";
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
channel: null,
|
channel: null
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getChannelData()
|
this.getChannelData();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchChannel() {
|
async fetchChannel() {
|
||||||
return await (
|
return await (
|
||||||
await fetch(Constants.BASE_URL + "/channels/" + this.$route.params.channelId)
|
await fetch(
|
||||||
|
Constants.BASE_URL +
|
||||||
|
"/channels/" +
|
||||||
|
this.$route.params.channelId
|
||||||
|
)
|
||||||
).json();
|
).json();
|
||||||
},
|
},
|
||||||
async getChannelData() {
|
async getChannelData() {
|
||||||
this.fetchChannel().then(data => this.channel = data)
|
this.fetchChannel()
|
||||||
.then(() => document.title = this.channel.name + " - Piped")
|
.then(data => (this.channel = data))
|
||||||
|
.then(() => (document.title = this.channel.name + " - Piped"));
|
||||||
},
|
},
|
||||||
timeFormat(duration) {
|
timeFormat(duration) {
|
||||||
|
var pad = function(num, size) {
|
||||||
var pad = function (num, size) {
|
return ("000" + num).slice(size * -1);
|
||||||
return ('000' + num).slice(size * -1);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
var time = parseFloat(duration).toFixed(3),
|
var time = parseFloat(duration).toFixed(3),
|
||||||
hours = Math.floor(time / 60 / 60),
|
hours = Math.floor(time / 60 / 60),
|
||||||
@ -54,14 +68,12 @@ export default {
|
|||||||
|
|
||||||
var str = "";
|
var str = "";
|
||||||
|
|
||||||
if (hours > 0)
|
if (hours > 0) str += pad(hours, 2) + ":";
|
||||||
str += pad(hours, 2) + ":"
|
|
||||||
|
|
||||||
str += pad(minutes, 2) + ':' + pad(seconds, 2)
|
str += pad(minutes, 2) + ":" + pad(seconds, 2);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
79
src/components/Preferences.vue
Normal file
79
src/components/Preferences.vue
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<template>
|
||||||
|
<table class="uk-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Instance Name</th>
|
||||||
|
<th>Instance Locations</th>
|
||||||
|
<th>Has CDN?</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody v-bind:key="instance.name" v-for="instance in instances">
|
||||||
|
<tr>
|
||||||
|
<td>{{ instance.name }}</td>
|
||||||
|
<td>{{ instance.locations }}</td>
|
||||||
|
<td>{{ instance.cdn }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<select
|
||||||
|
class="uk-select"
|
||||||
|
v-model="selectedInstance"
|
||||||
|
@change="onChange($event)"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
v-bind:key="instance.name"
|
||||||
|
v-for="instance in instances"
|
||||||
|
v-bind:value="instance.apiurl"
|
||||||
|
>
|
||||||
|
{{ instance.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedInstance: null,
|
||||||
|
instances: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
fetch(
|
||||||
|
"https://raw.githubusercontent.com/wiki/TeamPiped/Piped-Frontend/Instances.md"
|
||||||
|
)
|
||||||
|
.then(resp => resp.text())
|
||||||
|
.then(body => {
|
||||||
|
var skipped = 0;
|
||||||
|
const lines = body.split("\n");
|
||||||
|
lines.map(line => {
|
||||||
|
const split = line.split("|");
|
||||||
|
if (split.length == 4) {
|
||||||
|
if (skipped < 2) {
|
||||||
|
skipped++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.instances.push({
|
||||||
|
name: split[0].trim(),
|
||||||
|
apiurl: split[1].trim(),
|
||||||
|
locations: split[2].trim(),
|
||||||
|
cdn: split[3].trim()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (localStorage)
|
||||||
|
this.selectedInstance =
|
||||||
|
localStorage.getItem("instance") ||
|
||||||
|
"https://pipedapi.kavin.rocks";
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onChange() {
|
||||||
|
if (localStorage)
|
||||||
|
localStorage.setItem("instance", this.selectedInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
@ -1,45 +1,58 @@
|
|||||||
<template>
|
<template>
|
||||||
<h1 class="uk-text-bold uk-text-center">Trending</h1>
|
<h1 class="uk-text-bold uk-text-center">Trending</h1>
|
||||||
|
|
||||||
<hr>
|
<hr />
|
||||||
|
|
||||||
<div class="uk-grid-collapse" style="width: 100%" uk-grid="parallax: 0">
|
<div class="uk-grid-collapse" style="width: 100%" uk-grid="parallax: 0">
|
||||||
<div class="uk-tile-default" style="width: 300px; background: #0b0e0f" v-bind:key="video.url" v-for="video in videos">
|
<div
|
||||||
<div class="uk-card uk-card-default uk-card-body uk-grid-match uk-text-secondary" style="background: #0b0e0f">
|
class="uk-tile-default"
|
||||||
<router-link class="uk-text-emphasis" v-bind:to="video.url || '/'">
|
style="width: 300px; background: #0b0e0f"
|
||||||
<p>{{ video.title }}</p>
|
v-bind:key="video.url"
|
||||||
<img style="width: 100%" v-bind:src="video.thumbnail" />
|
v-for="video in videos"
|
||||||
</router-link>
|
>
|
||||||
<router-link class="uk-link-muted" v-bind:to="video.uploaderUrl || '/'">
|
<div
|
||||||
<p>{{ video.uploaderName }}</p>
|
class="uk-card uk-card-default uk-card-body uk-grid-match uk-text-secondary"
|
||||||
</router-link>
|
style="background: #0b0e0f"
|
||||||
<font-awesome-icon icon="eye"></font-awesome-icon> {{ video.views }} views
|
>
|
||||||
</div>
|
<router-link
|
||||||
</div>
|
class="uk-text-emphasis"
|
||||||
</div>
|
v-bind:to="video.url || '/'"
|
||||||
</template>
|
>
|
||||||
|
<p>{{ video.title }}</p>
|
||||||
<script>
|
<img style="width: 100%" v-bind:src="video.thumbnail" />
|
||||||
import Constants from '@/Constants.js'
|
</router-link>
|
||||||
|
<router-link
|
||||||
export default {
|
class="uk-link-muted"
|
||||||
data() {
|
v-bind:to="video.uploaderUrl || '/'"
|
||||||
return {
|
>
|
||||||
videos: [],
|
<p>{{ video.uploaderName }}</p>
|
||||||
};
|
</router-link>
|
||||||
},
|
<font-awesome-icon icon="eye"></font-awesome-icon>
|
||||||
mounted() {
|
{{ video.views }} views
|
||||||
|
</div>
|
||||||
document.title = "Trending - Piped";
|
</div>
|
||||||
|
</div>
|
||||||
this.fetchTrending().then(videos => this.videos = videos)
|
</template>
|
||||||
},
|
|
||||||
methods: {
|
<script>
|
||||||
async fetchTrending() {
|
import Constants from "@/Constants.js";
|
||||||
return await (
|
|
||||||
await fetch(Constants.BASE_URL + "/trending")
|
export default {
|
||||||
).json();
|
data() {
|
||||||
}
|
return {
|
||||||
}
|
videos: []
|
||||||
}
|
};
|
||||||
</script>
|
},
|
||||||
|
mounted() {
|
||||||
|
document.title = "Trending - Piped";
|
||||||
|
console.log(Constants.BASE_URL);
|
||||||
|
|
||||||
|
this.fetchTrending().then(videos => (this.videos = videos));
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async fetchTrending() {
|
||||||
|
return await (await fetch(Constants.BASE_URL + "/trending")).json();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
@ -1,42 +1,56 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="uk-container uk-container-xlarge">
|
<div class="uk-container uk-container-xlarge">
|
||||||
<h1 class="uk-text-bold">{{ video.title }}</h1>
|
<h1 class="uk-text-bold">{{ video.title }}</h1>
|
||||||
<video controls ref="player" class="video-js preview-player-dimensions "></video>
|
<video
|
||||||
|
controls
|
||||||
|
ref="player"
|
||||||
|
class="video-js preview-player-dimensions"
|
||||||
|
></video>
|
||||||
|
|
||||||
<img :src="video.uploaderAvatar" />
|
<img :src="video.uploaderAvatar" />
|
||||||
<router-link class="uk-text-bold" v-bind:to="video.uploaderUrl || '/'">
|
<router-link class="uk-text-bold" v-bind:to="video.uploaderUrl || '/'">
|
||||||
<a>{{ video.uploader }}</a>
|
<a>{{ video.uploader }}</a>
|
||||||
</router-link>
|
|
||||||
|
|
||||||
<p class="uk-dark">
|
|
||||||
<font-awesome-icon icon="thumbs-down"></font-awesome-icon>
|
|
||||||
{{ video.likes }}
|
|
||||||
<font-awesome-icon icon="thumbs-up"></font-awesome-icon>
|
|
||||||
{{ video.dislikes }}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<font-awesome-icon icon="eye"></font-awesome-icon> {{ video.views }} views
|
|
||||||
</p>
|
|
||||||
<p class="uk-light" v-html="video.description"></p>
|
|
||||||
<a v-if="sponsors && sponsors.segments">Sponsors Segments: {{ sponsors.segments.length }}</a>
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
|
|
||||||
<div class="uk-tile-default uk-text-secondary" style="background: #0b0e0f; width: 300px" v-bind:key="related.url" v-for="related in video.relatedStreams">
|
|
||||||
<router-link class="uk-link-muted" v-bind:to="related.url">
|
|
||||||
<p class="uk-text-emphasis">{{ related.title }}</p>
|
|
||||||
<img style="width: 100%" v-bind:src="related.thumbnail" />
|
|
||||||
</router-link>
|
</router-link>
|
||||||
<p>
|
|
||||||
<router-link class="uk-link-muted" v-bind:to="related.uploaderUrl || '/'">
|
|
||||||
<p>{{ related.uploaderName }}</p>
|
|
||||||
</router-link>
|
|
||||||
<font-awesome-icon icon="eye"></font-awesome-icon>
|
|
||||||
{{ related.views }} views
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
<p class="uk-dark">
|
||||||
|
<font-awesome-icon icon="thumbs-down"></font-awesome-icon>
|
||||||
|
{{ video.likes }}
|
||||||
|
<font-awesome-icon icon="thumbs-up"></font-awesome-icon>
|
||||||
|
{{ video.dislikes }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<font-awesome-icon icon="eye"></font-awesome-icon>
|
||||||
|
{{ video.views }} views
|
||||||
|
</p>
|
||||||
|
<p class="uk-light" v-html="video.description"></p>
|
||||||
|
<a v-if="sponsors && sponsors.segments"
|
||||||
|
>Sponsors Segments: {{ sponsors.segments.length }}</a
|
||||||
|
>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="uk-tile-default uk-text-secondary"
|
||||||
|
style="background: #0b0e0f; width: 300px"
|
||||||
|
v-bind:key="related.url"
|
||||||
|
v-for="related in video.relatedStreams"
|
||||||
|
>
|
||||||
|
<router-link class="uk-link-muted" v-bind:to="related.url">
|
||||||
|
<p class="uk-text-emphasis">{{ related.title }}</p>
|
||||||
|
<img style="width: 100%" v-bind:src="related.thumbnail" />
|
||||||
|
</router-link>
|
||||||
|
<p>
|
||||||
|
<router-link
|
||||||
|
class="uk-link-muted"
|
||||||
|
v-bind:to="related.uploaderUrl || '/'"
|
||||||
|
>
|
||||||
|
<p>{{ related.uploaderName }}</p>
|
||||||
|
</router-link>
|
||||||
|
<font-awesome-icon icon="eye"></font-awesome-icon>
|
||||||
|
{{ related.views }} views
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -52,11 +66,11 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
video: {
|
video: {
|
||||||
title: "Loading...",
|
title: "Loading..."
|
||||||
},
|
},
|
||||||
player: null,
|
player: null,
|
||||||
audioplayer: null,
|
audioplayer: null,
|
||||||
sponsors: null,
|
sponsors: null
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -68,37 +82,45 @@ export default {
|
|||||||
this.player.dispose();
|
this.player.dispose();
|
||||||
}
|
}
|
||||||
if (this.audioplayer) {
|
if (this.audioplayer) {
|
||||||
this.audioplayer.pause()
|
this.audioplayer.pause();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
"$route.query.v": function (v) {
|
"$route.query.v": function(v) {
|
||||||
if (v) {
|
if (v) {
|
||||||
if (this.audioplayer)
|
if (this.audioplayer) this.audioplayer.pause();
|
||||||
this.audioplayer.pause()
|
|
||||||
this.getVideoData();
|
this.getVideoData();
|
||||||
this.getSponsors();
|
this.getSponsors();
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async fetchVideo() {
|
async fetchVideo() {
|
||||||
return await (
|
return await (
|
||||||
await fetch(Constants.BASE_URL + "/streams/" + this.$route.query.v)
|
await fetch(
|
||||||
|
Constants.BASE_URL + "/streams/" + this.$route.query.v
|
||||||
|
)
|
||||||
).json();
|
).json();
|
||||||
},
|
},
|
||||||
async fetchSponsors() {
|
async fetchSponsors() {
|
||||||
return await (
|
return await (
|
||||||
await fetch(Constants.BASE_URL + "/sponsors/" + this.$route.query.v + "?category=[\"sponsor\",\"interaction\",\"selfpromo\",\"music_offtopic\"]")
|
await fetch(
|
||||||
|
Constants.BASE_URL +
|
||||||
|
"/sponsors/" +
|
||||||
|
this.$route.query.v +
|
||||||
|
'?category=["sponsor","interaction","selfpromo","music_offtopic"]'
|
||||||
|
)
|
||||||
).json();
|
).json();
|
||||||
},
|
},
|
||||||
async getVideoData() {
|
async getVideoData() {
|
||||||
this.fetchVideo()
|
this.fetchVideo()
|
||||||
.then((data) => (this.video = data))
|
.then(data => (this.video = data))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
document.title = this.video.title + " - Piped";
|
document.title = this.video.title + " - Piped";
|
||||||
|
|
||||||
this.video.description = this.video.description.replaceAll("http://www.youtube.com", "").replaceAll("https://www.youtube.com", "")
|
this.video.description = this.video.description
|
||||||
|
.replaceAll("http://www.youtube.com", "")
|
||||||
|
.replaceAll("https://www.youtube.com", "");
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
autoplay: false,
|
autoplay: false,
|
||||||
@ -110,22 +132,23 @@ export default {
|
|||||||
"volumePanel",
|
"volumePanel",
|
||||||
"qualitySelector",
|
"qualitySelector",
|
||||||
"captionsButton",
|
"captionsButton",
|
||||||
"fullscreenToggle",
|
"fullscreenToggle"
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
responsive: false,
|
responsive: false,
|
||||||
aspectRatio: '16:9'
|
aspectRatio: "16:9"
|
||||||
};
|
};
|
||||||
|
|
||||||
const noPrevPlayer = !this.player
|
const noPrevPlayer = !this.player;
|
||||||
|
|
||||||
if (noPrevPlayer) this.player = videojs(this.$refs.player, options);
|
if (noPrevPlayer)
|
||||||
|
this.player = videojs(this.$refs.player, options);
|
||||||
|
|
||||||
this.player.hotkeys({
|
this.player.hotkeys({
|
||||||
volumeStep: 0.1,
|
volumeStep: 0.1,
|
||||||
seekStep: 5,
|
seekStep: 5,
|
||||||
enableModifiersForNumbers: false,
|
enableModifiersForNumbers: false,
|
||||||
enableHoverScroll: true,
|
enableHoverScroll: true
|
||||||
});
|
});
|
||||||
|
|
||||||
this.player.poster(this.video.thumbnailUrl);
|
this.player.poster(this.video.thumbnailUrl);
|
||||||
@ -133,96 +156,110 @@ export default {
|
|||||||
var src = [];
|
var src = [];
|
||||||
|
|
||||||
if (this.video.livestream) {
|
if (this.video.livestream) {
|
||||||
|
|
||||||
src.push({
|
src.push({
|
||||||
src: this.video.hls,
|
src: this.video.hls,
|
||||||
type: 'application/x-mpegURL'
|
type: "application/x-mpegURL"
|
||||||
})
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.video.videoStreams.map((stream) =>
|
this.video.videoStreams.map(stream =>
|
||||||
src.push({
|
src.push({
|
||||||
src: stream.url,
|
src: stream.url,
|
||||||
type: stream.mimeType,
|
type: stream.mimeType,
|
||||||
label: stream.quality,
|
label: stream.quality
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.video.audioStreams.map((stream) =>
|
this.video.audioStreams.map(stream =>
|
||||||
src.push({
|
src.push({
|
||||||
src: stream.url,
|
src: stream.url,
|
||||||
type: stream.mimeType,
|
type: stream.mimeType,
|
||||||
label: stream.quality,
|
label: stream.quality
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.audioplayer = new Audio((this.video.audioStreams.slice(-1)[0].url));
|
this.audioplayer = new Audio(
|
||||||
|
this.video.audioStreams.slice(-1)[0].url
|
||||||
|
);
|
||||||
|
|
||||||
this.player.src(src);
|
this.player.src(src);
|
||||||
|
|
||||||
if (noPrevPlayer) {
|
if (noPrevPlayer) {
|
||||||
this.player.on('timeupdate', () => {
|
this.player.on("timeupdate", () => {
|
||||||
if (this.sponsors && this.sponsors.segments) {
|
if (this.sponsors && this.sponsors.segments) {
|
||||||
const time = this.player.currentTime()
|
const time = this.player.currentTime();
|
||||||
this.sponsors.segments.map(segment => {
|
this.sponsors.segments.map(segment => {
|
||||||
if (!segment.skipped) {
|
if (!segment.skipped) {
|
||||||
const end = segment.segment[1]
|
const end = segment.segment[1];
|
||||||
if (time >= segment.segment[0] && time < end) {
|
if (
|
||||||
this.player.currentTime(end)
|
time >= segment.segment[0] &&
|
||||||
this.audioplayer.currentTime = end
|
time < end
|
||||||
segment.skipped = true
|
) {
|
||||||
return
|
this.player.currentTime(end);
|
||||||
|
this.audioplayer.currentTime = end;
|
||||||
|
segment.skipped = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.audioplayer) {
|
if (this.audioplayer) {
|
||||||
|
const delay =
|
||||||
const delay = this.audioplayer.currentTime - this.player.currentTime()
|
this.audioplayer.currentTime -
|
||||||
|
this.player.currentTime();
|
||||||
|
|
||||||
if (Math.abs(delay) > 0.1) {
|
if (Math.abs(delay) > 0.1) {
|
||||||
this.audioplayer.currentTime = this.player.currentTime() - delay
|
this.audioplayer.currentTime =
|
||||||
|
this.player.currentTime() - delay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.player.on('play', () => {
|
this.player.on("play", () => {
|
||||||
this.audioplayer.play()
|
this.audioplayer.play();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.player.on('pause', () => {
|
this.player.on("pause", () => {
|
||||||
this.audioplayer.currentTime = this.player.currentTime()
|
this.audioplayer.currentTime = this.player.currentTime();
|
||||||
this.audioplayer.pause()
|
this.audioplayer.pause();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.player.on('volumechange', () => {
|
this.player.on("volumechange", () => {
|
||||||
this.audioplayer.volume = this.player.volume()
|
this.audioplayer.volume = this.player.volume();
|
||||||
})
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!noPrevPlayer)
|
if (!noPrevPlayer)
|
||||||
this.player.remoteTextTracks().map(track => this.player.removeRemoteTextTrack(track));
|
this.player
|
||||||
|
.remoteTextTracks()
|
||||||
|
.map(track =>
|
||||||
|
this.player.removeRemoteTextTrack(track)
|
||||||
|
);
|
||||||
|
|
||||||
this.video.subtitles.map(subtitle => {
|
this.video.subtitles.map(subtitle => {
|
||||||
this.player.addRemoteTextTrack({
|
this.player.addRemoteTextTrack(
|
||||||
kind: "captions",
|
{
|
||||||
src: subtitle.url.replace("fmt=ttml", "fmt=vtt"),
|
kind: "captions",
|
||||||
label: "Track",
|
src: subtitle.url.replace(
|
||||||
type: "captions/captions.vtt"
|
"fmt=ttml",
|
||||||
}, false).mode = "showing"
|
"fmt=vtt"
|
||||||
})
|
),
|
||||||
|
label: "Track",
|
||||||
|
type: "captions/captions.vtt"
|
||||||
|
},
|
||||||
|
false
|
||||||
|
).mode = "showing";
|
||||||
|
});
|
||||||
|
|
||||||
|
//const parent = this.player.el().querySelector(".vjs-progress-holder")
|
||||||
//TODO: Add sponsors on seekbar: https://github.com/ajayyy/SponsorBlock/blob/e39de9fd852adb9196e0358ed827ad38d9933e29/src/js-components/previewBar.ts#L12
|
//TODO: Add sponsors on seekbar: https://github.com/ajayyy/SponsorBlock/blob/e39de9fd852adb9196e0358ed827ad38d9933e29/src/js-components/previewBar.ts#L12
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
async getSponsors() {
|
async getSponsors() {
|
||||||
this.fetchSponsors().then((data) => (this.sponsors = data));
|
this.fetchSponsors().then(data => (this.sponsors = data));
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
36
src/main.js
36
src/main.js
@ -1,18 +1,18 @@
|
|||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { library } from '@fortawesome/fontawesome-svg-core'
|
import { library } from '@fortawesome/fontawesome-svg-core'
|
||||||
import { faThumbsUp, faThumbsDown, faEye } from '@fortawesome/free-solid-svg-icons'
|
import { faThumbsUp, faThumbsDown, faEye } from '@fortawesome/free-solid-svg-icons'
|
||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
||||||
library.add(faThumbsUp, faThumbsDown, faEye)
|
library.add(faThumbsUp, faThumbsDown, faEye)
|
||||||
|
|
||||||
require("uikit/src/less/uikit.less")
|
require("uikit/src/less/uikit.less")
|
||||||
require("uikit/dist/js/uikit.min.js")
|
require("uikit/dist/js/uikit.min.js")
|
||||||
|
|
||||||
import router from '@/router/router'
|
import router from '@/router/router'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
|
||||||
import './registerServiceWorker'
|
import './registerServiceWorker'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
app.component('font-awesome-icon', FontAwesomeIcon)
|
app.component('font-awesome-icon', FontAwesomeIcon)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
@ -21,7 +21,7 @@ if (process.env.NODE_ENV === 'production') {
|
|||||||
},
|
},
|
||||||
updated() {
|
updated() {
|
||||||
console.log('New content is available; please refresh.')
|
console.log('New content is available; please refresh.')
|
||||||
caches.keys().then(function(names) {
|
caches.keys().then(function (names) {
|
||||||
for (let name of names) caches.delete(name);
|
for (let name of names) caches.delete(name);
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
|
|||||||
import Watch from '../components/WatchVideo.vue'
|
import Watch from '../components/WatchVideo.vue'
|
||||||
import Trending from '../components/TrendingPage.vue'
|
import Trending from '../components/TrendingPage.vue'
|
||||||
import Channel from '../components/Channel.vue'
|
import Channel from '../components/Channel.vue'
|
||||||
|
import Preferences from '../components/Preferences.vue'
|
||||||
|
|
||||||
const routes = [{
|
const routes = [{
|
||||||
path: '/watch',
|
path: '/watch',
|
||||||
@ -15,6 +16,10 @@ const routes = [{
|
|||||||
path: '/channel/:channelId',
|
path: '/channel/:channelId',
|
||||||
name: 'Channel',
|
name: 'Channel',
|
||||||
component: Channel
|
component: Channel
|
||||||
|
}, {
|
||||||
|
path: '/preferences',
|
||||||
|
name: 'Preferences',
|
||||||
|
component: Preferences
|
||||||
}]
|
}]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
@ -22,4 +27,4 @@ const router = createRouter({
|
|||||||
routes
|
routes
|
||||||
})
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
Loading…
Reference in New Issue
Block a user