Merge pull request #116 from TeamPiped/fix/prettier-config

Add Prettier config and format code
This commit is contained in:
Maurice Oegerli 2021-04-07 14:20:05 +02:00 committed by GitHub
commit 4700b198e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 336 additions and 525 deletions

2
.prettierignore Normal file
View File

@ -0,0 +1,2 @@
dist
node_modules

11
.prettierrc.json Normal file
View File

@ -0,0 +1,11 @@
{
"singleQuote": false,
"trailingComma": "all",
"semi": true,
"tabWidth": 4,
"embeddedLanguageFormatting": "auto",
"endOfLine": "lf",
"printWidth": 120,
"vueIndentScriptAndStyle": false,
"quoteProps": "as-needed"
}

View File

@ -8,15 +8,11 @@
<div style="text-align: center">
<a href="https://github.com/TeamPiped/Piped">
<font-awesome-icon
:icon="['fab', 'github']"
></font-awesome-icon>
<font-awesome-icon :icon="['fab', 'github']"></font-awesome-icon>
</a>
&nbsp;
<a href="bitcoin://13MoHioctZkC7LDSZSb4m32TDT8xNmei1p">
<font-awesome-icon
:icon="['fab', 'bitcoin']"
></font-awesome-icon>
<font-awesome-icon :icon="['fab', 'bitcoin']"></font-awesome-icon>
13MoHioctZkC7LDSZSb4m32TDT8xNmei1p
</a>
</div>

View File

@ -1,4 +1,4 @@
export default {
BASE_URL: localStorage.getItem("instance") || 'https://pipedapi.kavin.rocks',
AUTO_PLAY: localStorage.getItem("autoplay") || false
}
BASE_URL: localStorage.getItem("instance") || "https://pipedapi.kavin.rocks",
AUTO_PLAY: localStorage.getItem("autoplay") || false,
};

View File

@ -1,14 +1,7 @@
<template>
<div v-if="channel">
<h1 class="uk-text-center">
<img v-bind:src="channel.avatarUrl" />{{ channel.name }}
</h1>
<img
v-if="channel.bannerUrl"
v-bind:src="channel.bannerUrl"
style="width: 100%"
loading="lazy"
/>
<h1 class="uk-text-center"><img v-bind:src="channel.avatarUrl" />{{ channel.name }}</h1>
<img v-if="channel.bannerUrl" v-bind:src="channel.bannerUrl" style="width: 100%" loading="lazy" />
<p v-html="this.channel.description.replaceAll('\n', '<br>')"></p>
<hr />
@ -19,15 +12,8 @@
v-bind:key="item.url"
v-for="item in this.channel.relatedStreams"
>
<router-link
class="uk-link-muted uk-text-justify"
v-bind:to="item.url || '/'"
>
<img
style="width: 100%"
v-bind:src="item.thumbnail"
loading="lazy"
/>
<router-link class="uk-link-muted uk-text-justify" v-bind:to="item.url || '/'">
<img style="width: 100%" v-bind:src="item.thumbnail" loading="lazy" />
<a>{{ item.title }}</a>
</router-link>
<br />
@ -53,7 +39,7 @@ import Constants from "@/Constants.js";
export default {
data() {
return {
channel: null
channel: null,
};
},
mounted() {
@ -65,9 +51,7 @@ export default {
},
methods: {
async fetchChannel() {
return await this.fetchJson(
Constants.BASE_URL + "/channels/" + this.$route.params.channelId
);
return await this.fetchJson(Constants.BASE_URL + "/channels/" + this.$route.params.channelId);
},
async getChannelData() {
this.fetchChannel()
@ -75,17 +59,8 @@ export default {
.then(() => (document.title = this.channel.name + " - Piped"));
},
handleScroll() {
if (
this.loading ||
!this.channel ||
!this.channel.nextpage ||
!this.channel.nextid
)
return;
if (
window.innerHeight + window.scrollY >=
document.body.offsetHeight - window.innerHeight
) {
if (this.loading || !this.channel || !this.channel.nextpage || !this.channel.nextid) return;
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - window.innerHeight) {
this.loading = true;
this.fetchJson(
Constants.BASE_URL +
@ -94,18 +69,16 @@ export default {
"?url=" +
encodeURIComponent(this.channel.nextpage) +
"&id=" +
encodeURIComponent(this.channel.nextid)
encodeURIComponent(this.channel.nextid),
).then(json => {
this.channel.relatedStreams.concat(json.relatedStreams);
this.channel.nextpage = json.nextpage;
this.channel.nextid = json.nextid;
this.loading = false;
json.relatedStreams.map(stream =>
this.channel.relatedStreams.push(stream)
);
json.relatedStreams.map(stream => this.channel.relatedStreams.push(stream));
});
}
}
}
},
},
};
</script>

View File

@ -1,11 +1,7 @@
<template>
<div class="uk-container-expand">
<div data-shaka-player-container>
<video
data-shaka-player
autoplay
style="width: 100%; height: 100%"
></video>
<video data-shaka-player autoplay style="width: 100%; height: 100%"></video>
</div>
</div>
</template>
@ -18,7 +14,7 @@ export default {
props: {
video: Object,
sponsors: Object,
selectedAutoPlay: Boolean
selectedAutoPlay: Boolean,
},
methods: {
loadVideo() {
@ -37,7 +33,7 @@ export default {
const dash = require("@/utils/DashUtils.js").default.generate_dash_file_from_formats(
streams,
this.video.duration
this.video.duration,
);
if (noPrevPlayer)
@ -74,15 +70,11 @@ export default {
});
videoEl.addEventListener("volumechange", () => {
if (localStorage)
localStorage.setItem("volume", videoEl.volume);
if (localStorage) localStorage.setItem("volume", videoEl.volume);
});
videoEl.addEventListener("ended", () => {
if (
this.selectedAutoPlay &&
this.video.relatedStreams.length > 0
)
if (this.selectedAutoPlay && this.video.relatedStreams.length > 0)
this.$router.push(this.video.relatedStreams[0].url);
});
}
@ -90,52 +82,33 @@ export default {
//TODO: Add sponsors on seekbar: https://github.com/ajayyy/SponsorBlock/blob/e39de9fd852adb9196e0358ed827ad38d9933e29/src/js-components/previewBar.ts#L12
},
setPlayerAttrs(player, videoEl, dash, shaka) {
player
.load(
"data:application/dash+xml;charset=utf-8;base64," +
btoa(dash)
)
.then(() => {
player.load("data:application/dash+xml;charset=utf-8;base64," + btoa(dash)).then(() => {
this.video.subtitles.map(subtitle => {
player.addTextTrack(
subtitle.url,
"eng",
"SUBTITLE",
subtitle.mimeType,
null,
"English"
);
player.addTextTrack(subtitle.url, "eng", "SUBTITLE", subtitle.mimeType, null, "English");
player.setTextTrackVisibility(true);
});
if (localStorage)
videoEl.volume = localStorage.getItem("volume") || 1;
if (localStorage) videoEl.volume = localStorage.getItem("volume") || 1;
const ui =
this.ui ||
(this.ui = new shaka.ui.Overlay(
player,
document.querySelector(
"div[data-shaka-player-container]"
),
videoEl
document.querySelector("div[data-shaka-player-container]"),
videoEl,
));
const config = {
overflowMenuButtons: [
"quality",
"captions",
"playback_rate"
],
overflowMenuButtons: ["quality", "captions", "playback_rate"],
seekBarColors: {
base: "rgba(255, 255, 255, 0.3)",
buffered: "rgba(255, 255, 255, 0.54)",
played: "rgb(255, 0, 0)"
}
played: "rgb(255, 0, 0)",
},
};
ui.configure(config);
});
}
},
},
beforeUnmount() {
if (this.player) {
@ -143,6 +116,6 @@ export default {
this.player = undefined;
this.ui = undefined;
}
}
},
};
</script>

View File

@ -6,10 +6,7 @@
</h1>
<b
><router-link
class="uk-text-justify"
v-bind:to="playlist.uploaderUrl || '/'"
>
><router-link class="uk-text-justify" v-bind:to="playlist.uploaderUrl || '/'">
<img v-bind:src="playlist.uploaderAvatar" loading="lazy" />
{{ playlist.uploader }}</router-link
></b
@ -25,25 +22,16 @@
v-bind:key="item.url"
v-for="item in this.playlist.relatedStreams"
>
<router-link
class="uk-link-muted uk-text-justify"
v-bind:to="item.url || '/'"
>
<img
style="width: 100%"
v-bind:src="item.thumbnail"
loading="lazy"
/>
<router-link class="uk-link-muted uk-text-justify" v-bind:to="item.url || '/'">
<img style="width: 100%" v-bind:src="item.thumbnail" loading="lazy" />
<a>{{ item.title }}</a>
</router-link>
<br />
<div>
<b class="uk-text-small uk-align-left">
<router-link
class="uk-text-justify"
v-bind:to="item.uploaderUrl || '/'"
>{{ item.uploaderName }}</router-link
>
<router-link class="uk-text-justify" v-bind:to="item.uploaderUrl || '/'">{{
item.uploaderName
}}</router-link>
</b>
<b class="uk-text-small uk-align-right">
{{ timeFormat(item.duration) }}
@ -60,7 +48,7 @@ import Constants from "@/Constants.js";
export default {
data() {
return {
playlist: null
playlist: null,
};
},
mounted() {
@ -72,9 +60,7 @@ export default {
},
methods: {
async fetchPlaylist() {
return await await this.fetchJson(
Constants.BASE_URL + "/playlists/" + this.$route.query.list
);
return await await this.fetchJson(Constants.BASE_URL + "/playlists/" + this.$route.query.list);
},
async getPlaylistData() {
this.fetchPlaylist()
@ -82,17 +68,8 @@ export default {
.then(() => (document.title = this.playlist.name + " - Piped"));
},
handleScroll() {
if (
this.loading ||
!this.playlist ||
!this.playlist.nextpage ||
!this.playlist.nextid
)
return;
if (
window.innerHeight + window.scrollY >=
document.body.offsetHeight - window.innerHeight
) {
if (this.loading || !this.playlist || !this.playlist.nextpage || !this.playlist.nextid) return;
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - window.innerHeight) {
this.loading = true;
this.fetchJson(
Constants.BASE_URL +
@ -101,18 +78,16 @@ export default {
"?url=" +
encodeURIComponent(this.playlist.nextpage) +
"&id=" +
encodeURIComponent(this.playlist.nextid)
encodeURIComponent(this.playlist.nextid),
).then(json => {
this.playlist.relatedStreams.concat(json.relatedStreams);
this.playlist.nextpage = json.nextpage;
this.playlist.nextid = json.nextid;
this.loading = false;
json.relatedStreams.map(stream =>
this.playlist.relatedStreams.push(stream)
);
json.relatedStreams.map(stream => this.playlist.relatedStreams.push(stream));
});
}
}
}
},
},
};
</script>

View File

@ -2,71 +2,34 @@
<h1 class="uk-text-bold uk-text-center">Preferences</h1>
<hr />
<h2>SponsorBlock</h2>
<p>
Uses the API from <a href="https://sponsor.ajay.app/">sponsor.ajay.app</a>
</p>
<p>Uses the API from <a href="https://sponsor.ajay.app/">sponsor.ajay.app</a></p>
<b>Enable Sponsorblock</b>
<br />
<input
class="uk-checkbox"
v-model="sponsorBlock"
@change="onChange($event)"
type="checkbox"
/>
<input class="uk-checkbox" v-model="sponsorBlock" @change="onChange($event)" type="checkbox" />
<br />
<b>Skip Sponsors</b>
<br />
<input
class="uk-checkbox"
v-model="skipSponsor"
@change="onChange($event)"
type="checkbox"
/>
<input class="uk-checkbox" v-model="skipSponsor" @change="onChange($event)" type="checkbox" />
<br />
<b>Skip Intermission/Intro Animation</b>
<br />
<input
class="uk-checkbox"
v-model="skipIntro"
@change="onChange($event)"
type="checkbox"
/>
<input class="uk-checkbox" v-model="skipIntro" @change="onChange($event)" type="checkbox" />
<br />
<b>Skip Endcards/Credits</b>
<br />
<input
class="uk-checkbox"
v-model="skipOutro"
@change="onChange($event)"
type="checkbox"
/>
<input class="uk-checkbox" v-model="skipOutro" @change="onChange($event)" type="checkbox" />
<br />
<b>Skip Interaction Reminder (Subscribe)</b>
<br />
<input
class="uk-checkbox"
v-model="skipInteraction"
@change="onChange($event)"
type="checkbox"
/>
<input class="uk-checkbox" v-model="skipInteraction" @change="onChange($event)" type="checkbox" />
<br />
<b>Skip Unpaid/Self Promotion</b>
<br />
<input
class="uk-checkbox"
v-model="skipSelfPromo"
@change="onChange($event)"
type="checkbox"
/>
<input class="uk-checkbox" v-model="skipSelfPromo" @change="onChange($event)" type="checkbox" />
<br />
<b>Skip Music: Non-Music Section</b>
<br />
<input
class="uk-checkbox"
v-model="skipMusicOffTopic"
@change="onChange($event)"
type="checkbox"
/>
<input class="uk-checkbox" v-model="skipMusicOffTopic" @change="onChange($event)" type="checkbox" />
<h2>Instances List</h2>
<table class="uk-table">
<thead>
@ -83,9 +46,7 @@
<td>{{ instance.locations }}</td>
<td>{{ instance.cdn }}</td>
<td>
<a :href="sslScore(instance.apiurl)" target="_blank"
>Click Here</a
>
<a :href="sslScore(instance.apiurl)" target="_blank">Click Here</a>
</td>
</tr>
</tbody>
@ -94,16 +55,8 @@
<hr />
<b>Instance Selection:</b>
<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"
>
<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>
@ -121,13 +74,11 @@ export default {
skipOutro: false,
skipInteraction: true,
skipSelfPromo: true,
skipMusicOffTopic: true
skipMusicOffTopic: true,
};
},
mounted() {
fetch(
"https://raw.githubusercontent.com/wiki/TeamPiped/Piped-Frontend/Instances.md"
)
fetch("https://raw.githubusercontent.com/wiki/TeamPiped/Piped-Frontend/Instances.md")
.then(resp => resp.text())
.then(body => {
var skipped = 0;
@ -143,16 +94,14 @@ export default {
name: split[0].trim(),
apiurl: split[1].trim(),
locations: split[2].trim(),
cdn: split[3].trim()
cdn: split[3].trim(),
});
}
});
});
if (localStorage) {
this.selectedInstance =
localStorage.getItem("instance") ||
"https://pipedapi.kavin.rocks";
this.selectedInstance = localStorage.getItem("instance") || "https://pipedapi.kavin.rocks";
this.sponsorBlock = localStorage.getItem("sponsorblock") || true;
if (localStorage.getItem("selectedSkip")) {
@ -198,18 +147,13 @@ export default {
if (this.skipOutro) sponsorSelected.push("outro");
if (this.skipInteraction) sponsorSelected.push("interaction");
if (this.skipSelfPromo) sponsorSelected.push("selfpromo");
if (this.skipMusicOffTopic)
sponsorSelected.push("music_offtopic");
if (this.skipMusicOffTopic) sponsorSelected.push("music_offtopic");
localStorage.setItem("selectedSkip", sponsorSelected);
}
},
sslScore(url) {
return (
"https://www.ssllabs.com/ssltest/analyze.html?d=" +
new URL(url).host +
"&latest"
);
}
}
return "https://www.ssllabs.com/ssltest/analyze.html?d=" + new URL(url).host + "&latest";
},
},
};
</script>

View File

@ -11,21 +11,11 @@
v-for="result in results.items"
>
<div class="uk-text-secondary" style="background: #0b0e0f">
<router-link
class="uk-text-emphasis"
v-bind:to="result.url || '/'"
>
<img
style="width: 100%"
v-bind:src="result.thumbnail"
loading="lazy"
/>
<router-link class="uk-text-emphasis" v-bind:to="result.url || '/'">
<img style="width: 100%" v-bind:src="result.thumbnail" loading="lazy" />
<p>{{ result.name }}</p>
</router-link>
<router-link
class="uk-link-muted"
v-bind:to="result.uploaderUrl || '/'"
>
<router-link class="uk-link-muted" v-bind:to="result.uploaderUrl || '/'">
<p>{{ result.uploaderName }}</p>
</router-link>
{{ result.duration ? timeFormat(result.duration) : "" }}
@ -48,7 +38,7 @@ import Constants from "@/Constants.js";
export default {
data() {
return {
results: null
results: null,
};
},
mounted() {
@ -61,28 +51,21 @@ export default {
watch: {
"$route.query.search_query": function(q) {
if (q) this.updateResults();
}
},
},
methods: {
async fetchResults() {
return await await this.fetchJson(
Constants.BASE_URL +
"/search?q=" +
encodeURIComponent(this.$route.query.search_query)
Constants.BASE_URL + "/search?q=" + encodeURIComponent(this.$route.query.search_query),
);
},
async updateResults() {
document.title = this.$route.query.search_query + " - Piped";
this.results = this.fetchResults().then(
json => (this.results = json)
);
this.results = this.fetchResults().then(json => (this.results = json));
},
handleScroll() {
if (this.loading || !this.results || !this.results.nextpage) return;
if (
window.innerHeight + window.scrollY >=
document.body.offsetHeight - window.innerHeight
) {
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - window.innerHeight) {
this.loading = true;
this.fetchJson(
Constants.BASE_URL +
@ -92,7 +75,7 @@ export default {
"&id=" +
encodeURIComponent(this.results.id) +
"&q=" +
encodeURIComponent(this.$route.query.search_query)
encodeURIComponent(this.$route.query.search_query),
).then(json => {
this.results.nextpage = json.nextpage;
this.results.id = json.id;
@ -100,7 +83,7 @@ export default {
json.items.map(stream => this.results.items.push(stream));
});
}
}
}
},
},
};
</script>

View File

@ -11,21 +11,11 @@
v-for="video in videos"
>
<div class="uk-text-secondary" style="background: #0b0e0f">
<router-link
class="uk-text-emphasis"
v-bind:to="video.url || '/'"
>
<img
style="width: 100%"
v-bind:src="video.thumbnail"
loading="lazy"
/>
<router-link class="uk-text-emphasis" v-bind:to="video.url || '/'">
<img style="width: 100%" v-bind:src="video.thumbnail" loading="lazy" />
<p>{{ video.title }}</p>
</router-link>
<router-link
class="uk-link-muted"
v-bind:to="video.uploaderUrl || '/'"
>
<router-link class="uk-link-muted" v-bind:to="video.uploaderUrl || '/'">
<p>{{ video.uploaderName }}</p>
</router-link>
<b class="uk-text-small uk-align-left">
@ -48,7 +38,7 @@ import Constants from "@/Constants.js";
export default {
data() {
return {
videos: []
videos: [],
};
},
mounted() {
@ -59,7 +49,7 @@ export default {
methods: {
async fetchTrending() {
return await this.fetchJson(Constants.BASE_URL + "/trending");
}
}
},
},
};
</script>

View File

@ -1,11 +1,6 @@
<template>
<div class="uk-container uk-container-xlarge">
<Player
ref="videoPlayer"
:video="video"
:sponsors="sponsors"
:selectedAutoPlay="selectedAutoPlay"
/>
<Player ref="videoPlayer" :video="video" :sponsors="sponsors" :selectedAutoPlay="selectedAutoPlay" />
<h1 class="uk-text-bold">{{ video.title }}</h1>
<img :src="video.uploaderAvatar" loading="lazy" />
@ -27,27 +22,16 @@
<p>
Uploaded on <b>{{ video.uploadDate }}</b>
</p>
<a
class="uk-button uk-button-small"
style="background: #222"
@click="showDesc = !showDesc"
>
<a class="uk-button uk-button-small" style="background: #222" @click="showDesc = !showDesc">
{{ showDesc ? "+" : "-" }}
</a>
<p v-show="showDesc" class="uk-light" v-html="video.description"></p>
<a v-if="sponsors && sponsors.segments"
>Sponsors Segments: {{ sponsors.segments.length }}</a
>
<a v-if="sponsors && sponsors.segments">Sponsors Segments: {{ sponsors.segments.length }}</a>
<hr />
<b>Auto Play next Video:</b>&nbsp;
<input
class="uk-checkbox"
v-model="selectedAutoPlay"
@change="onChange($event)"
type="checkbox"
/>
<input class="uk-checkbox" v-model="selectedAutoPlay" @change="onChange($event)" type="checkbox" />
<div
class="uk-tile-default uk-text-secondary"
@ -57,17 +41,10 @@
>
<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"
loading="lazy"
/>
<img style="width: 100%" v-bind:src="related.thumbnail" loading="lazy" />
</router-link>
<p>
<router-link
class="uk-link-muted"
v-bind:to="related.uploaderUrl || '/'"
>
<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>
@ -86,11 +63,11 @@ export default {
data() {
return {
video: {
title: "Loading..."
title: "Loading...",
},
sponsors: null,
selectedAutoPlay: null,
showDesc: true
showDesc: true,
};
},
mounted() {
@ -104,13 +81,11 @@ export default {
this.getVideoData();
this.getSponsors();
}
}
},
},
methods: {
fetchVideo() {
return this.fetchJson(
Constants.BASE_URL + "/streams/" + this.$route.query.v
);
return this.fetchJson(Constants.BASE_URL + "/streams/" + this.$route.query.v);
},
async fetchSponsors() {
return await this.fetchJson(
@ -119,21 +94,12 @@ export default {
this.$route.query.v +
"?category=" +
(localStorage && localStorage.getItem("selectedSkip")
? encodeURIComponent(
'["' +
localStorage
.getItem("selectedSkip")
.replace(",", '","') +
'"]'
)
: encodeURIComponent(
'["sponsor", "interaction", "selfpromo", "music_offtopic"]'
))
? encodeURIComponent('["' + localStorage.getItem("selectedSkip").replace(",", '","') + '"]')
: encodeURIComponent('["sponsor", "interaction", "selfpromo", "music_offtopic"]')),
);
},
onChange() {
if (localStorage)
localStorage.setItem("autoplay", this.selectedAutoPlay);
if (localStorage) localStorage.setItem("autoplay", this.selectedAutoPlay);
},
async getVideoData() {
this.fetchVideo()
@ -154,10 +120,10 @@ export default {
async getSponsors() {
if (!localStorage || localStorage.getItem("sponsorblock") !== false)
this.fetchSponsors().then(data => (this.sponsors = data));
}
},
},
components: {
Player
}
Player,
},
};
</script>

View File

@ -1,22 +1,21 @@
import { createApp } from 'vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faThumbsUp, faThumbsDown, faEye } from '@fortawesome/free-solid-svg-icons'
import { faGithub, faBitcoin } from '@fortawesome/free-brands-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
library.add(faThumbsUp, faThumbsDown, faEye, faGithub, faBitcoin)
import { createApp } from "vue";
import { library } from "@fortawesome/fontawesome-svg-core";
import { faThumbsUp, faThumbsDown, faEye } from "@fortawesome/free-solid-svg-icons";
import { faGithub, faBitcoin } from "@fortawesome/free-brands-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
library.add(faThumbsUp, faThumbsDown, faEye, faGithub, faBitcoin);
import("uikit/src/less/uikit.less")
import("uikit/dist/js/uikit.min.js")
import("uikit/src/less/uikit.less");
import("uikit/dist/js/uikit.min.js");
import router from '@/router/router'
import App from './App.vue'
import router from "@/router/router";
import App from "./App.vue";
import './registerServiceWorker'
import "./registerServiceWorker";
const mixin = {
methods: {
timeFormat: function(duration) {
var pad = function(num, size) {
return ("000" + num).slice(size * -1);
};
@ -33,19 +32,17 @@ const mixin = {
str += pad(minutes, 2) + ":" + pad(seconds, 2);
return str;
},
fetchJson: function(url, options) {
return fetch(url, options)
.then(response => {
return fetch(url, options).then(response => {
return response.json();
})
}
}
}
});
},
},
};
const app = createApp(App)
app.use(router)
app.mixin(mixin)
app.component('font-awesome-icon', FontAwesomeIcon)
app.mount('#app')
const app = createApp(App);
app.use(router);
app.mixin(mixin);
app.component("font-awesome-icon", FontAwesomeIcon);
app.mount("#app");

View File

@ -1,33 +1,33 @@
/* eslint-disable no-console */
import { register } from 'register-service-worker'
import { register } from "register-service-worker";
if (process.env.NODE_ENV === 'production') {
if (process.env.NODE_ENV === "production") {
register(`/service-worker.js`, {
ready() {
console.log(
'App is being served from cache by a service worker.\n' +
'For more details, visit https://goo.gl/AFskqB'
)
"App is being served from cache by a service worker.\n" +
"For more details, visit https://goo.gl/AFskqB",
);
},
registered() {
console.log('Service worker has been registered.')
console.log("Service worker has been registered.");
},
cached() {
console.log('Content has been cached for offline use.')
console.log("Content has been cached for offline use.");
},
updatefound() {
console.log('New content is downloading.')
console.log("New content is downloading.");
},
updated() {
console.log('New content is available; please refresh.')
window.location.reload()
console.log("New content is available; please refresh.");
window.location.reload();
},
offline() {
console.log('No internet connection found. App is running in offline mode.')
console.log("No internet connection found. App is running in offline mode.");
},
error(error) {
console.error('Error during service worker registration:', error)
}
})
console.error("Error during service worker registration:", error);
},
});
}

View File

@ -1,34 +1,41 @@
import { createRouter, createWebHistory } from 'vue-router'
import { createRouter, createWebHistory } from "vue-router";
const routes = [{
path: '/watch',
name: 'Watch',
component: () => import('../components/WatchVideo.vue')
}, {
path: '/',
name: 'Trending',
component: () => import('../components/TrendingPage.vue')
}, {
path: '/channel/:channelId',
name: 'Channel',
component: () => import('../components/Channel.vue')
}, {
path: '/preferences',
name: 'Preferences',
component: () => import('../components/Preferences.vue')
}, {
path: '/results',
name: 'SearchResults',
component: () => import('../components/SearchResults.vue')
}, {
path: '/playlist',
name: 'Playlist',
component: () => import('../components/Playlist.vue')
}]
const routes = [
{
path: "/watch",
name: "Watch",
component: () => import("../components/WatchVideo.vue"),
},
{
path: "/",
name: "Trending",
component: () => import("../components/TrendingPage.vue"),
},
{
path: "/channel/:channelId",
name: "Channel",
component: () => import("../components/Channel.vue"),
},
{
path: "/preferences",
name: "Preferences",
component: () => import("../components/Preferences.vue"),
},
{
path: "/results",
name: "SearchResults",
component: () => import("../components/SearchResults.vue"),
},
{
path: "/playlist",
name: "Playlist",
component: () => import("../components/Playlist.vue"),
},
];
const router = createRouter({
history: createWebHistory(),
routes
})
routes,
});
export default router
export default router;

View File

@ -1,189 +1,188 @@
// Based of https://github.com/GilgusMaximus/yt-dash-manifest-generator/blob/master/src/DashGenerator.js
const xml = require('xml-js')
const xml = require("xml-js");
const DashUtils = {
generate_dash_file_from_formats(VideoFormats, VideoLength) {
const generatedJSON = this.generate_xmljs_json_from_data(VideoFormats, VideoLength)
return xml.json2xml(generatedJSON)
const generatedJSON = this.generate_xmljs_json_from_data(VideoFormats, VideoLength);
return xml.json2xml(generatedJSON);
},
generate_xmljs_json_from_data(VideoFormatArray, VideoLength) {
const convertJSON = {
"declaration": {
"attributes": {
"version": "1.0",
"encoding": "utf-8"
}
declaration: {
attributes: {
version: "1.0",
encoding: "utf-8",
},
"elements": [
{
"type": "element",
"name": "MPD",
"attributes": {
"xmlns": "urn:mpeg:dash:schema:mpd:2011",
"profiles": "urn:mpeg:dash:profile:full:2011",
"minBufferTime": "PT1.5S",
"type": "static",
"mediaPresentationDuration": `PT${VideoLength}S`
},
"elements": [
elements: [
{
"type": "element",
"name": "Period",
"elements": this.generate_adaptation_set(VideoFormatArray)
}
]
}
]
}
return convertJSON
type: "element",
name: "MPD",
attributes: {
xmlns: "urn:mpeg:dash:schema:mpd:2011",
profiles: "urn:mpeg:dash:profile:full:2011",
minBufferTime: "PT1.5S",
type: "static",
mediaPresentationDuration: `PT${VideoLength}S`,
},
elements: [
{
type: "element",
name: "Period",
elements: this.generate_adaptation_set(VideoFormatArray),
},
],
},
],
};
return convertJSON;
},
generate_adaptation_set(VideoFormatArray) {
const adaptationSets = []
const mimeTypes = []
const mimeObjects = [[]]
const adaptationSets = [];
const mimeTypes = [];
const mimeObjects = [[]];
// sort the formats by mime types
VideoFormatArray.forEach((videoFormat) => {
VideoFormatArray.forEach(videoFormat => {
// the dual formats should not be used
if (videoFormat.mimeType.indexOf("video") != -1 && !videoFormat.videoOnly) {
return
return;
}
// if these properties are not available, then we skip it because we cannot set these properties
//if (!(videoFormat.hasOwnProperty('initRange') && videoFormat.hasOwnProperty('indexRange'))) {
// return
//}
const mimeType = videoFormat.mimeType
const mimeTypeIndex = mimeTypes.indexOf(mimeType)
const mimeType = videoFormat.mimeType;
const mimeTypeIndex = mimeTypes.indexOf(mimeType);
if (mimeTypeIndex > -1) {
mimeObjects[mimeTypeIndex].push(videoFormat)
mimeObjects[mimeTypeIndex].push(videoFormat);
} else {
mimeTypes.push(mimeType)
mimeObjects.push([])
mimeObjects[mimeTypes.length - 1].push(videoFormat)
mimeTypes.push(mimeType);
mimeObjects.push([]);
mimeObjects[mimeTypes.length - 1].push(videoFormat);
}
})
});
// for each MimeType generate a new Adaptation set with Representations as sub elements
for (let i = 0; i < mimeTypes.length; i++) {
let isVideoFormat = false
let isVideoFormat = false;
const adapSet = {
"type": "element",
"name": "AdaptationSet",
"attributes": {
"id": i,
"mimeType": mimeTypes[i],
"startWithSAP": "1",
"subsegmentAlignment": "true"
type: "element",
name: "AdaptationSet",
attributes: {
id: i,
mimeType: mimeTypes[i],
startWithSAP: "1",
subsegmentAlignment: "true",
},
"elements": []
}
elements: [],
};
if (!mimeTypes[i].includes("audio")) {
adapSet.attributes.scanType = "progressive"
isVideoFormat = true
adapSet.attributes.scanType = "progressive";
isVideoFormat = true;
}
mimeObjects[i].forEach((format) => {
mimeObjects[i].forEach(format => {
if (isVideoFormat) {
adapSet.elements.push(this.generate_representation_video(format))
adapSet.elements.push(this.generate_representation_video(format));
} else {
adapSet.elements.push(this.generate_representation_audio(format))
adapSet.elements.push(this.generate_representation_audio(format));
}
})
adaptationSets.push(adapSet)
});
adaptationSets.push(adapSet);
}
return adaptationSets
}, generate_representation_audio(Format) {
const representation =
{
"type": "element",
"name": "Representation",
"attributes": {
"id": Format.itag,
"codecs": Format.codec,
"bandwidth": Format.bitrate
return adaptationSets;
},
"elements": [
generate_representation_audio(Format) {
const representation = {
type: "element",
name: "Representation",
attributes: {
id: Format.itag,
codecs: Format.codec,
bandwidth: Format.bitrate,
},
elements: [
{
"type": "element",
"name": "AudioChannelConfiguration",
"attributes": {
"schemeIdUri": "urn:mpeg:dash:23003:3:audio_channel_configuration:2011",
"value": "2"
type: "element",
name: "AudioChannelConfiguration",
attributes: {
schemeIdUri: "urn:mpeg:dash:23003:3:audio_channel_configuration:2011",
value: "2",
},
},
{
"type": "element",
"name": "BaseURL",
"elements": [
type: "element",
name: "BaseURL",
elements: [
{
"type": "text",
"text": Format.url
}
]
type: "text",
text: Format.url,
},
],
},
{
"type": "element",
"name": "SegmentBase",
"attributes": {
"indexRange": `${Format.indexStart}-${Format.indexEnd}`
type: "element",
name: "SegmentBase",
attributes: {
indexRange: `${Format.indexStart}-${Format.indexEnd}`,
},
"elements": [
elements: [
{
"type": "element",
"name": "Initialization",
"attributes": {
"range": `${Format.initStart}-${Format.initEnd}`
}
}
]
}
]
}
return representation
type: "element",
name: "Initialization",
attributes: {
range: `${Format.initStart}-${Format.initEnd}`,
},
},
],
},
],
};
return representation;
},
generate_representation_video(Format) {
const representation =
{
"type": "element",
"name": "Representation",
"attributes": {
"id": Format.itag,
"codecs": Format.codec,
"bandwidth": Format.bitrate,
"width": Format.width,
"height": Format.height,
"maxPlayoutRate": "1",
"frameRate": Format.fps
const representation = {
type: "element",
name: "Representation",
attributes: {
id: Format.itag,
codecs: Format.codec,
bandwidth: Format.bitrate,
width: Format.width,
height: Format.height,
maxPlayoutRate: "1",
frameRate: Format.fps,
},
"elements": [
elements: [
{
"type": "element",
"name": "BaseURL",
"elements": [
type: "element",
name: "BaseURL",
elements: [
{
"type": "text",
"text": Format.url
}
]
type: "text",
text: Format.url,
},
],
},
{
"type": "element",
"name": "SegmentBase",
"attributes": {
"indexRange": `${Format.indexStart}-${Format.indexEnd}`
type: "element",
name: "SegmentBase",
attributes: {
indexRange: `${Format.indexStart}-${Format.indexEnd}`,
},
"elements": [
elements: [
{
"type": "element",
"name": "Initialization",
"attributes": {
"range": `${Format.initStart}-${Format.initEnd}`
}
}
]
}
]
}
return representation
}
}
type: "element",
name: "Initialization",
attributes: {
range: `${Format.initStart}-${Format.initEnd}`,
},
},
],
},
],
};
return representation;
},
};
export default DashUtils;

View File

@ -2907,16 +2907,11 @@ core-js@^2.4.0:
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
core-js@^3.10.0:
core-js@^3.10.0, core-js@^3.6.5:
version "3.10.0"
resolved "https://registry.npm.taobao.org/core-js/download/core-js-3.10.0.tgz?cache=0&sync_timestamp=1617182041689&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-3.10.0.tgz#9a020547c8b6879f929306949e31496bbe2ae9b3"
integrity sha1-mgIFR8i2h5+SkwaUnjFJa74q6bM=
core-js@^3.6.5:
version "3.10.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.10.0.tgz#9a020547c8b6879f929306949e31496bbe2ae9b3"
integrity sha512-MQx/7TLgmmDVamSyfE+O+5BHvG1aUGj/gHhLn1wVtm2B5u1eVIPvh7vkfjwWKNCjrTJB8+He99IntSQ1qP+vYQ==
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"