Make eslint work, and fix all warnings. (#511)

* Make eslint work, and fix all warnings.

* Don't ignore v-html rule globally.

* Remove eslint file and merge in package.json.
This commit is contained in:
Kavin 2021-10-08 19:52:51 +01:00 committed by GitHub
parent 41ac97ed92
commit 92d61a23af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 412 additions and 362 deletions

View file

@ -1,5 +1,3 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
presets: ["@vue/cli-plugin-babel/preset"],
};

View file

@ -34,6 +34,8 @@
"@vue/compiler-sfc": "3.2.19",
"babel-eslint": "^10.1.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^7.19.1"
},
"eslintConfig": {
@ -43,6 +45,7 @@
},
"extends": [
"plugin:vue/vue3-essential",
"plugin:prettier/recommended",
"eslint:recommended"
],
"parserOptions": {

View file

@ -7,7 +7,7 @@
<Navigation />
<router-view v-slot="{ Component }">
<keep-alive :max="5">
<component :key="$route.fullPath" :is="Component" />
<component :is="Component" :key="$route.fullPath" />
</keep-alive>
</router-view>

View file

@ -3,17 +3,18 @@
<div v-if="channel" v-show="!channel.error">
<h1 class="uk-text-center">
<img height="48" width="48" class="uk-border-circle" v-bind:src="channel.avatarUrl" />{{ channel.name }}
<img height="48" width="48" class="uk-border-circle" :src="channel.avatarUrl" />{{ channel.name }}
</h1>
<img v-if="channel.bannerUrl" v-bind:src="channel.bannerUrl" style="width: 100%" loading="lazy" />
<img v-if="channel.bannerUrl" :src="channel.bannerUrl" style="width: 100%" loading="lazy" />
<!-- eslint-disable-next-line vue/no-v-html -->
<p style="white-space: pre-wrap"><span v-html="purifyHTML(urlify(channel.description))"></span></p>
<button
v-if="authenticated"
@click="subscribeHandler"
class="uk-button uk-button-small"
style="background: #222"
type="button"
@click="subscribeHandler"
>
{{ subscribed ? $t("actions.unsubscribe") : $t("actions.subscribe") }}
</button>
@ -22,11 +23,11 @@
<div class="uk-grid-xl" uk-grid="parallax: 0">
<div
v-for="video in channel.relatedStreams"
:key="video.url"
class="uk-width-1-2 uk-width-1-3@m uk-width-1-4@l uk-width-1-5@xl"
v-bind:key="video.url"
v-for="video in this.channel.relatedStreams"
>
<VideoItem :video="video" height="94" width="168" hideChannel />
<VideoItem :video="video" height="94" width="168" hide-channel />
</div>
</div>
</div>
@ -37,6 +38,10 @@ import ErrorHandler from "@/components/ErrorHandler.vue";
import VideoItem from "@/components/VideoItem.vue";
export default {
components: {
ErrorHandler,
VideoItem,
},
data() {
return {
channel: null,
@ -116,9 +121,5 @@ export default {
this.subscribed = !this.subscribed;
},
},
components: {
ErrorHandler,
VideoItem,
},
};
</script>

View file

@ -1,47 +1,52 @@
<template>
<div class="comment uk-flex">
<img
:src="comment.thumbnail"
class="comment-avatar uk-border-circle uk-margin-right"
style="width: 48px; height: 48px;"
loading="lazy"
alt="Avatar"
/>
<div class="comment uk-flex">
<img
:src="comment.thumbnail"
class="comment-avatar uk-border-circle uk-margin-right"
style="width: 48px; height: 48px;"
loading="lazy"
alt="Avatar"
/>
<div class="comment-content">
<div class="comment-header">
<div v-if="comment.pinned" class="comment-pinned uk-text-meta">
<font-awesome-icon icon="thumbtack"></font-awesome-icon>&nbsp; {{ $t("comment.pinned_by") }}
{{ uploader }}
</div>
<div class="comment-content">
<div class="comment-header">
<div v-if="comment.pinned" class="comment-pinned uk-text-meta">
<font-awesome-icon icon="thumbtack"></font-awesome-icon>&nbsp; {{ $t("comment.pinned_by") }}
{{ uploader }}
</div>
<div class="comment-author">
<router-link class="uk-text-bold uk-text-small" v-bind:to="comment.commentorUrl">
{{ comment.author }} </router-link
>&thinsp;<font-awesome-icon v-if="comment.verified" icon="check"></font-awesome-icon>
<div class="comment-author">
<router-link class="uk-text-bold uk-text-small" :to="comment.commentorUrl">
{{ comment.author }} </router-link
>&thinsp;<font-awesome-icon v-if="comment.verified" icon="check"></font-awesome-icon>
</div>
<div class="comment-meta uk-text-meta uk-margin-small-bottom">
{{ comment.commentedTime }}
</div>
</div>
<div class="comment-body" style="white-space: pre-wrap">
{{ comment.commentText }}
</div>
<div class="comment-footer uk-margin-small-top uk-text-meta">
<font-awesome-icon icon="thumbs-up" style="margin-right: 4px;"></font-awesome-icon>
<span>{{ numberFormat(comment.likeCount) }}</span>
&nbsp;
<font-awesome-icon v-if="comment.hearted" icon="heart"></font-awesome-icon>
</div>
</div>
<div class="comment-meta uk-text-meta uk-margin-small-bottom">
{{ comment.commentedTime }}
</div>
</div>
<div class="comment-body" style="white-space: pre-wrap">
{{ comment.commentText }}
</div>
<div class="comment-footer uk-margin-small-top uk-text-meta">
<font-awesome-icon icon="thumbs-up" style="margin-right: 4px;"></font-awesome-icon>
<span>{{ numberFormat(comment.likeCount) }}</span>
&nbsp;
<font-awesome-icon v-if="comment.hearted" icon="heart"></font-awesome-icon>
</div>
</div>
</div>
</template>
<script>
export default {
export default {
props: {
comment: Object,
uploader: String
}
}
</script>
comment: {
type: Object,
default: () => {
return {};
},
},
uploader: { type: String, default: null },
},
};
</script>

View file

@ -9,8 +9,8 @@
<script>
export default {
props: {
error: String,
message: String,
error: { type: String, default: null },
message: { type: String, default: null },
},
};
</script>

View file

@ -1,12 +1,12 @@
<template>
<h1 class="uk-text-bold uk-text-center" v-t="'titles.feed'" />
<h1 v-t="'titles.feed'" class="uk-text-bold uk-text-center" />
<button
v-if="authenticated"
@click="exportHandler"
class="uk-button uk-button-small"
style="background: #222; margin-right: 0.5rem"
type="button"
@click="exportHandler"
>
<router-link to="/subscriptions">
Subscriptions
@ -19,11 +19,11 @@
<span class="uk-align-right@m">
<label for="ddlSortBy">{{ $t("actions.sort_by") }}</label>
<select id="ddlSortBy" class="uk-select uk-width-auto" v-model="selectedSort" @change="onChange()">
<option value="descending" v-t="'actions.most_recent'" />
<option value="ascending" v-t="'actions.least_recent'" />
<option value="channel_ascending" v-t="'actions.channel_name_asc'" />
<option value="channel_descending" v-t="'actions.channel_name_desc'" />
<select id="ddlSortBy" v-model="selectedSort" class="uk-select uk-width-auto" @change="onChange()">
<option v-t="'actions.most_recent'" value="descending" />
<option v-t="'actions.least_recent'" value="ascending" />
<option v-t="'actions.channel_name_asc'" value="channel_ascending" />
<option v-t="'actions.channel_name_desc'" value="channel_descending" />
</select>
</span>
@ -31,10 +31,10 @@
<div class="uk-grid-xl" uk-grid="parallax: 0">
<div
v-for="video in videos"
:key="video.url"
:style="[{ background: backgroundColor }]"
class="uk-width-1-1 uk-width-1-3@s uk-width-1-4@m uk-width-1-5@l uk-width-1-6@xl"
v-bind:key="video.url"
v-for="video in videos"
>
<VideoItem :video="video" />
</div>
@ -45,6 +45,9 @@
import VideoItem from "@/components/VideoItem.vue";
export default {
components: {
VideoItem,
},
data() {
return {
currentVideoCount: 0,
@ -54,6 +57,11 @@ export default {
selectedSort: "descending",
};
},
computed: {
getRssUrl(_this) {
return _this.apiUrl() + "/feed/rss?authToken=" + _this.getAuthToken();
},
},
mounted() {
this.fetchFeed().then(videos => {
this.videosStore = videos;
@ -105,13 +113,5 @@ export default {
}
},
},
computed: {
getRssUrl(_this) {
return _this.apiUrl() + "/feed/rss?authToken=" + _this.getAuthToken();
},
},
components: {
VideoItem,
},
};
</script>

View file

@ -1,14 +1,13 @@
<template>
<h1 class="uk-text-bold uk-text-center">{{ $t("titles.history") }}</h1>
<div style="text-align: right">
<label for="ddlSortBy">{{ $t("actions.sort_by") }}</label>
<select id="ddlSortBy" class="uk-select uk-width-auto" v-model="selectedSort" @change="onChange()">
<option value="descending" v-t="'actions.most_recent'" />
<option value="ascending" v-t="'actions.least_recent'" />
<option value="channel_ascending" v-t="'actions.channel_name_asc'" />
<option value="channel_descending" v-t="'actions.channel_name_desc'" />
<select id="ddlSortBy" v-model="selectedSort" class="uk-select uk-width-auto" @change="onChange()">
<option v-t="'actions.most_recent'" value="descending" />
<option v-t="'actions.least_recent'" value="ascending" />
<option v-t="'actions.channel_name_asc'" value="channel_ascending" />
<option v-t="'actions.channel_name_desc'" value="channel_descending" />
</select>
</div>
@ -16,10 +15,10 @@
<div class="uk-grid-xl" uk-grid="parallax: 0">
<div
v-for="video in videos"
:key="video.url"
:style="[{ background: backgroundColor }]"
class="uk-width-1-2 uk-width-1-3@s uk-width-1-4@m uk-width-1-5@l uk-width-1-6@xl"
v-bind:key="video.url"
v-for="video in videos"
>
<VideoItem :video="video" />
</div>
@ -32,6 +31,9 @@
import VideoItem from "@/components/VideoItem.vue";
export default {
components: {
VideoItem,
},
data() {
return {
videos: [],
@ -85,8 +87,5 @@ export default {
}
},
},
components: {
VideoItem,
},
};
</script>

View file

@ -2,13 +2,13 @@
<div class="uk-vertical-align uk-text-center uk-height-1-1 ">
<form class="uk-panel uk-panel-box">
<div class="uk-form-row">
<input type="file" @change="fileChange" ref="fileSelector" />
<input ref="fileSelector" type="file" @change="fileChange" />
</div>
<div class="uk-form-row">
<b>Selected Subscriptions: {{ selectedSubscriptions }}</b>
</div>
<div class="uk-form-row">
<b>Override: <input class="uk-checkbox" v-model="override" type="checkbox"/></b>
<b>Override: <input v-model="override" class="uk-checkbox" type="checkbox"/></b>
</div>
<div class="uk-form-row">
<a
@ -79,7 +79,7 @@ export default {
},
methods: {
fileChange() {
const file = this.$refs.fileSelector.files[0]
const file = this.$refs.fileSelector.files[0];
file.text().then(text => {
this.subscriptions = [];

View file

@ -3,9 +3,9 @@
<form class="uk-panel uk-panel-box">
<div class="uk-form-row">
<input
v-model="username"
class="uk-width-1-1 uk-form-large uk-input uk-width-auto"
type="text"
v-model="username"
autocomplete="username"
:placeholder="$t('login.username')"
:aria-label="$t('login.username')"
@ -13,9 +13,9 @@
</div>
<div class="uk-form-row">
<input
v-model="password"
class="uk-width-1-1 uk-form-large uk-input uk-width-auto"
type="password"
v-model="password"
autocomplete="password"
:placeholder="$t('login.password')"
:aria-label="$t('login.password')"
@ -26,8 +26,9 @@
class="uk-width-1-1 uk-button uk-button-primary uk-button-large uk-width-auto"
style="background: #222"
@click="login"
> {{ $t('titles.login') }} </a
>
{{ $t("titles.login") }}
</a>
</div>
</form>
</div>

View file

@ -17,12 +17,12 @@
</div>
<div class="uk-navbar-center uk-flex uk-visible@m">
<input
v-model="searchText"
class="uk-input uk-width-medium"
type="text"
role="search"
:title="$t('actions.search')"
:placeholder="$t('actions.search')"
v-model="searchText"
@keyup="onKeyUp"
@focus="onInputFocus"
@blur="onInputBlur"
@ -31,31 +31,31 @@
<div class="uk-navbar-right">
<ul class="uk-navbar-nav">
<li>
<router-link to="/preferences" v-t="'titles.preferences'" />
<router-link v-t="'titles.preferences'" to="/preferences" />
</li>
<li v-if="shouldShowLogin">
<router-link to="/login" v-t="'titles.login'" />
<router-link v-t="'titles.login'" to="/login" />
</li>
<li v-if="shouldShowLogin">
<router-link to="/register" v-t="'titles.register'" />
<router-link v-t="'titles.register'" to="/register" />
</li>
<li v-if="shouldShowHistory">
<router-link to="/history" v-t="'titles.history'" />
<router-link v-t="'titles.history'" to="/history" />
</li>
<li v-if="authenticated">
<router-link to="/feed" v-t="'titles.feed'" />
<router-link v-t="'titles.feed'" to="/feed" />
</li>
</ul>
</div>
</nav>
<div class="uk-container-expand uk-hidden@m">
<input
v-model="searchText"
class="uk-input"
type="text"
role="search"
:title="$t('actions.search')"
:placeholder="$t('actions.search')"
v-model="searchText"
@keyup="onKeyUp"
@focus="onInputFocus"
@blur="onInputBlur"
@ -63,9 +63,9 @@
</div>
<SearchSuggestions
v-show="searchText && suggestionsVisible"
:searchText="searchText"
@searchchange="onSearchTextChange"
ref="searchSuggestions"
:search-text="searchText"
@searchchange="onSearchTextChange"
/>
</template>

View file

@ -1,40 +1,22 @@
<template>
<div class="uk-container-expand">
<div
ref="container"
data-shaka-player-container
style="width: 100%; height: 100%; background: #000"
:style="!isEmbed ? { 'max-height': '75vh', 'min-height': '250px' } : {}"
ref="container"
>
<video
ref="videoEl"
data-shaka-player
class="uk-width-expand"
:autoplay="shouldAutoPlay"
:loop="selectedAutoLoop"
ref="videoEl"
></video>
</div>
</div>
</template>
<style>
.shaka-text-container > div {
height: auto !important;
width: auto !important;
top: auto !important;
left: auto !important;
}
.shaka-text-container * {
background-color: rgba(8, 8, 8, 0.75) !important;
color: white !important;
}
.shaka-video-container:-webkit-full-screen {
max-height: none !important;
}
</style>
<script>
import("shaka-player/dist/controls.css");
const shaka = import("shaka-player/dist/shaka-player.ui.js");
@ -43,8 +25,18 @@ window.muxjs = muxjs;
export default {
props: {
video: Object,
sponsors: Object,
video: {
type: Object,
default: () => {
return {};
},
},
sponsors: {
type: Object,
default: () => {
return {};
},
},
selectedAutoPlay: Boolean,
selectedAutoLoop: Boolean,
isEmbed: Boolean,
@ -82,6 +74,63 @@ export default {
mounted() {
if (!this.shaka) this.shakaPromise = shaka.then(shaka => shaka.default).then(shaka => (this.shaka = shaka));
},
activated() {
import("hotkeys-js")
.then(mod => mod.default)
.then(hotkeys => {
this.hotkeys = hotkeys;
var self = this;
hotkeys("f,m,j,k,l,space,up,down,left,right", function(e, handler) {
const videoEl = self.$refs.videoEl;
switch (handler.key) {
case "f":
self.$ui.getControls().toggleFullScreen();
e.preventDefault();
break;
case "m":
videoEl.muted = !videoEl.muted;
e.preventDefault();
break;
case "j":
videoEl.currentTime = Math.max(videoEl.currentTime - 15, 0);
e.preventDefault();
break;
case "l":
videoEl.currentTime = videoEl.currentTime + 15;
e.preventDefault();
break;
case "k":
case "space":
if (videoEl.paused) videoEl.play();
else videoEl.pause();
e.preventDefault();
break;
case "up":
videoEl.volume = Math.min(videoEl.volume + 0.05, 1);
e.preventDefault();
break;
case "down":
videoEl.volume = Math.max(videoEl.volume - 0.05, 0);
e.preventDefault();
break;
case "left":
videoEl.currentTime = Math.max(videoEl.currentTime - 5, 0);
e.preventDefault();
break;
case "right":
videoEl.currentTime = videoEl.currentTime + 5;
e.preventDefault();
break;
}
});
});
},
deactivated() {
this.destroy();
},
unmounted() {
this.destroy();
},
methods: {
async loadVideo() {
const component = this;
@ -304,62 +353,23 @@ export default {
if (this.$refs.container) this.$refs.container.querySelectorAll("div").forEach(node => node.remove());
},
},
activated() {
import("hotkeys-js")
.then(mod => mod.default)
.then(hotkeys => {
this.hotkeys = hotkeys;
var self = this;
hotkeys("f,m,j,k,l,space,up,down,left,right", function(e, handler) {
const videoEl = self.$refs.videoEl;
switch (handler.key) {
case "f":
self.$ui.getControls().toggleFullScreen();
e.preventDefault();
break;
case "m":
videoEl.muted = !videoEl.muted;
e.preventDefault();
break;
case "j":
videoEl.currentTime = Math.max(videoEl.currentTime - 15, 0);
e.preventDefault();
break;
case "l":
videoEl.currentTime = videoEl.currentTime + 15;
e.preventDefault();
break;
case "k":
case "space":
if (videoEl.paused) videoEl.play();
else videoEl.pause();
e.preventDefault();
break;
case "up":
videoEl.volume = Math.min(videoEl.volume + 0.05, 1);
e.preventDefault();
break;
case "down":
videoEl.volume = Math.max(videoEl.volume - 0.05, 0);
e.preventDefault();
break;
case "left":
videoEl.currentTime = Math.max(videoEl.currentTime - 5, 0);
e.preventDefault();
break;
case "right":
videoEl.currentTime = videoEl.currentTime + 5;
e.preventDefault();
break;
}
});
});
},
deactivated() {
this.destroy();
},
unmounted() {
this.destroy();
},
};
</script>
<style>
.shaka-text-container > div {
height: auto !important;
width: auto !important;
top: auto !important;
left: auto !important;
}
.shaka-text-container * {
background-color: rgba(8, 8, 8, 0.75) !important;
color: white !important;
}
.shaka-video-container:-webkit-full-screen {
max-height: none !important;
}
</style>

View file

@ -3,13 +3,13 @@
<div v-if="playlist" v-show="!playlist.error">
<h1 class="uk-text-center">
<img v-bind:src="playlist.avatarUrl" height="48" width="48" loading="lazy"/>
<img :src="playlist.avatarUrl" height="48" width="48" loading="lazy" />
{{ playlist.name }}
</h1>
<b
><router-link class="uk-text-justify" v-bind:to="playlist.uploaderUrl || '/'">
<img v-bind:src="playlist.uploaderAvatar" loading="lazy" class="uk-border-circle" />
><router-link class="uk-text-justify" :to="playlist.uploaderUrl || '/'">
<img :src="playlist.uploaderAvatar" loading="lazy" class="uk-border-circle" />
{{ playlist.uploader }}</router-link
></b
>
@ -24,9 +24,9 @@
<div class="uk-grid-xl" uk-grid="parallax: 0">
<div
v-for="video in playlist.relatedStreams"
:key="video.url"
class="uk-width-1-2 uk-width-1-3@m uk-width-1-4@l uk-width-1-5@xl"
v-bind:key="video.url"
v-for="video in this.playlist.relatedStreams"
>
<VideoItem :video="video" height="94" width="168" />
</div>
@ -39,11 +39,20 @@ import ErrorHandler from "@/components/ErrorHandler.vue";
import VideoItem from "@/components/VideoItem.vue";
export default {
components: {
ErrorHandler,
VideoItem,
},
data() {
return {
playlist: null,
};
},
computed: {
getRssUrl: _this => {
return _this.apiUrl() + "/rss/playlists/" + _this.$route.query.list;
},
},
mounted() {
this.getPlaylistData();
},
@ -53,11 +62,6 @@ export default {
deactivated() {
window.removeEventListener("scroll", this.handleScroll);
},
computed: {
getRssUrl: _this => {
return _this.apiUrl() + "/rss/playlists/" + _this.$route.query.list;
},
},
methods: {
async fetchPlaylist() {
return await await this.fetchJson(this.apiUrl() + "/playlists/" + this.$route.query.list);
@ -82,9 +86,5 @@ export default {
}
},
},
components: {
ErrorHandler,
VideoItem,
},
};
</script>

View file

@ -3,7 +3,7 @@
<button class="uk-button uk-button-text" @click="$router.go(-1) || $router.push('/')">
<font-awesome-icon icon="chevron-left" /> &nbsp;{{ $t("actions.back") }}
</button>
<span><h1 class="uk-text-bold uk-text-center" v-t="'titles.preferences'"/></span>
<span><h1 v-t="'titles.preferences'" class="uk-text-bold uk-text-center"/></span>
<span />
</div>
<hr />
@ -13,158 +13,163 @@
<br />
<input
id="chkEnableSponsorblock"
class="uk-checkbox"
v-model="sponsorBlock"
@change="onChange($event)"
class="uk-checkbox"
type="checkbox"
@change="onChange($event)"
/>
<br />
<label for="chkSkipSponsors"><b v-t="'actions.skip_sponsors'"/></label>
<br />
<input id="chkSkipSponsors" class="uk-checkbox" v-model="skipSponsor" @change="onChange($event)" type="checkbox" />
<input id="chkSkipSponsors" v-model="skipSponsor" class="uk-checkbox" type="checkbox" @change="onChange($event)" />
<br />
<label for="chkSkipIntro"><b v-t="'actions.skip_intro'"/></label>
<br />
<input id="chkSkipIntro" class="uk-checkbox" v-model="skipIntro" @change="onChange($event)" type="checkbox" />
<input id="chkSkipIntro" v-model="skipIntro" class="uk-checkbox" type="checkbox" @change="onChange($event)" />
<br />
<label for="chkSkipOutro"><b v-t="'actions.skip_outro'"/></label>
<br />
<input id="chkSkipOutro" class="uk-checkbox" v-model="skipOutro" @change="onChange($event)" type="checkbox" />
<input id="chkSkipOutro" v-model="skipOutro" class="uk-checkbox" type="checkbox" @change="onChange($event)" />
<br />
<label for="chkSkipPreview"><b v-t="'actions.skip_preview'"/></label>
<br />
<input id="chkSkipPreview" class="uk-checkbox" v-model="skipPreview" @change="onChange($event)" type="checkbox" />
<input id="chkSkipPreview" v-model="skipPreview" class="uk-checkbox" type="checkbox" @change="onChange($event)" />
<br />
<label for="chkSkipInteraction"><b v-t="'actions.skip_interaction'"/></label>
<br />
<input
id="chkSkipInteraction"
class="uk-checkbox"
v-model="skipInteraction"
@change="onChange($event)"
class="uk-checkbox"
type="checkbox"
@change="onChange($event)"
/>
<br />
<label for="chkSkipSelfPromo"><b v-t="'actions.skip_self_promo'"/></label>
<br />
<input
id="chkSkipSelfPromo"
class="uk-checkbox"
v-model="skipSelfPromo"
@change="onChange($event)"
class="uk-checkbox"
type="checkbox"
@change="onChange($event)"
/>
<br />
<label for="chkSkipNonMusic"><b v-t="'actions.skip_non_music'"/></label>
<br />
<input
id="chkSkipNonMusic"
class="uk-checkbox"
v-model="skipMusicOffTopic"
@change="onChange($event)"
class="uk-checkbox"
type="checkbox"
@change="onChange($event)"
/>
<br />
<label for="ddlTheme"><b v-t="'actions.theme'"/></label>
<br />
<select id="ddlTheme" class="uk-select uk-width-auto" v-model="selectedTheme" @change="onChange($event)">
<option value="auto" v-t="'actions.auto'" />
<option value="dark" v-t="'actions.dark'" />
<option value="light" v-t="'actions.light'" />
<select id="ddlTheme" v-model="selectedTheme" class="uk-select uk-width-auto" @change="onChange($event)">
<option v-t="'actions.auto'" value="auto" />
<option v-t="'actions.dark'" value="dark" />
<option v-t="'actions.light'" value="light" />
</select>
<br />
<label for="chkAutoPlayVideo"><b v-t="'actions.autoplay_video'"/></label>
<br />
<input
id="chkAutoPlayVideo"
class="uk-checkbox"
v-model="autoPlayVideo"
@change="onChange($event)"
class="uk-checkbox"
type="checkbox"
@change="onChange($event)"
/>
<br />
<label for="chkAudioOnly"><b v-t="'actions.audio_only'"/></label>
<br />
<input id="chkAudioOnly" class="uk-checkbox" v-model="listen" @change="onChange($event)" type="checkbox" />
<input id="chkAudioOnly" v-model="listen" class="uk-checkbox" type="checkbox" @change="onChange($event)" />
<br />
<label for="ddlDefaultQuality"><b v-t="'actions.default_quality'"/></label>
<br />
<select id="ddlDefaultQuality" class="uk-select uk-width-auto" v-model="defaultQuality" @change="onChange($event)">
<option value="0" v-t="'actions.auto'" />
<option :key="resolution" v-for="resolution in resolutions" :value="resolution">{{ resolution }}p</option>
<select id="ddlDefaultQuality" v-model="defaultQuality" class="uk-select uk-width-auto" @change="onChange($event)">
<option v-t="'actions.auto'" value="0" />
<option v-for="resolution in resolutions" :key="resolution" :value="resolution">{{ resolution }}p</option>
</select>
<br />
<label for="txtBufferingGoal"><b v-t="'actions.buffering_goal'"/></label>
<br />
<input
id="txtBufferingGoal"
class="uk-input uk-width-auto"
v-model="bufferingGoal"
@change="onChange($event)"
class="uk-input uk-width-auto"
type="text"
@change="onChange($event)"
/>
<br />
<label for="ddlCountrySelection"><b v-t="'actions.country_selection'"/></label>
<br />
<select id="ddlCountrySelection" class="uk-select uk-width-auto" v-model="country" @change="onChange($event)">
<option :key="country.code" v-for="country in countryMap" :value="country.code">{{ country.name }}</option>
<select
id="ddlCountrySelection"
v-model="countrySelected"
class="uk-select uk-width-auto"
@change="onChange($event)"
>
<option v-for="country in countryMap" :key="country.code" :value="country.code">{{ country.name }}</option>
</select>
<br />
<label for="ddlDefaultHomepage"><b v-t="'actions.default_homepage'"/></label>
<br />
<select
id="ddlDefaultHomepage"
class="uk-select uk-width-auto"
v-model="defaultHomepage"
class="uk-select uk-width-auto"
@change="onChange($event)"
>
<option value="trending" v-t="'titles.trending'" />
<option value="feed" v-t="'titles.feed'" />
<option v-t="'titles.trending'" value="trending" />
<option v-t="'titles.feed'" value="feed" />
</select>
<br />
<label for="chkShowComments"><b v-t="'actions.show_comments'"/></label>
<br />
<input id="chkShowComments" class="uk-checkbox" v-model="showComments" @change="onChange($event)" type="checkbox" />
<input id="chkShowComments" v-model="showComments" class="uk-checkbox" type="checkbox" @change="onChange($event)" />
<br />
<label for="chkMinimizeDescription"><b v-t="'actions.minimize_description_default'"/></label>
<br />
<input
id="chkMinimizeDescription"
class="uk-checkbox"
v-model="minimizeDescription"
@change="onChange($event)"
class="uk-checkbox"
type="checkbox"
@change="onChange($event)"
/>
<br />
<label for="chkStoreWatchHistory"><b v-t="'actions.store_watch_history'"/></label>
<br />
<input
id="chkStoreWatchHistory"
class="uk-checkbox"
v-model="watchHistory"
@change="onChange($event)"
class="uk-checkbox"
type="checkbox"
@change="onChange($event)"
/>
<br />
<label for="ddlLanguageSelection"><b v-t="'actions.language_selection'"/></label>
<br />
<select
id="ddlLanguageSelection"
class="uk-select uk-width-auto"
v-model="selectedLanguage"
class="uk-select uk-width-auto"
@change="onChange($event)"
>
<option :key="language.code" v-for="language in languages" :value="language.code">{{ language.name }}</option>
<option v-for="language in languages" :key="language.code" :value="language.code">{{ language.name }}</option>
</select>
<br />
<label for="ddlEnabledCodecs"><b v-t="'actions.enabled_codecs'"/></label>
<br />
<select
id="ddlEnabledCodecs"
class="uk-select uk-width-auto"
v-model="enabledCodecs"
@change="onChange($event)"
class="uk-select uk-width-auto"
multiple
@change="onChange($event)"
>
<option value="av1">AV1</option>
<option value="vp9">VP9</option>
@ -173,11 +178,11 @@
<br />
<label for="chkDisableLBRY"><b v-t="'actions.disable_lbry'"/></label>
<br />
<input id="chkDisableLBRY" class="uk-checkbox" v-model="disableLBRY" @change="onChange($event)" type="checkbox" />
<input id="chkDisableLBRY" v-model="disableLBRY" class="uk-checkbox" type="checkbox" @change="onChange($event)" />
<br />
<label for="chkEnableLBRYProxy"><b v-t="'actions.enable_lbry_proxy'"/></label>
<br />
<input id="chkEnableLBRYProxy" class="uk-checkbox" v-model="proxyLBRY" @change="onChange($event)" type="checkbox" />
<input id="chkEnableLBRYProxy" v-model="proxyLBRY" class="uk-checkbox" type="checkbox" @change="onChange($event)" />
<h2 v-t="'actions.instances_list'" />
<table class="uk-table">
<thead>
@ -188,7 +193,7 @@
<th>{{ $t("preferences.ssl_score") }}</th>
</tr>
</thead>
<tbody v-bind:key="instance.name" v-for="instance in instances">
<tbody v-for="instance in instances" :key="instance.name">
<tr>
<td>{{ instance.name }}</td>
<td>{{ instance.locations }}</td>
@ -208,11 +213,11 @@
<br />
<select
id="ddlInstanceSelection"
class="uk-select uk-width-auto"
v-model="selectedInstance"
class="uk-select uk-width-auto"
@change="onChange($event)"
>
<option v-bind:key="instance.name" v-for="instance in instances" v-bind:value="instance.apiurl">
<option v-for="instance in instances" :key="instance.name" :value="instance.apiurl">
{{ instance.name }}
</option>
</select>
@ -240,7 +245,7 @@ export default {
defaultQuality: 0,
bufferingGoal: 10,
countryMap: CountryMap,
country: "US",
countrySelected: "US",
defaultHomepage: "trending",
showComments: true,
minimizeDescription: false,
@ -347,7 +352,7 @@ export default {
this.listen = this.getPreferenceBoolean("listen", false);
this.defaultQuality = Number(localStorage.getItem("quality"));
this.bufferingGoal = Math.max(Number(localStorage.getItem("bufferGoal")), 10);
this.country = this.getPreferenceString("region", "US");
this.countrySelected = this.getPreferenceString("region", "US");
this.defaultHomepage = this.getPreferenceString("homepage", "trending");
this.showComments = this.getPreferenceBoolean("comments", true);
this.minimizeDescription = this.getPreferenceBoolean("minimizeDescription", false);
@ -400,7 +405,7 @@ export default {
localStorage.setItem("listen", this.listen);
localStorage.setItem("quality", this.defaultQuality);
localStorage.setItem("bufferGoal", this.bufferingGoal);
localStorage.setItem("region", this.country);
localStorage.setItem("region", this.countrySelected);
localStorage.setItem("homepage", this.defaultHomepage);
localStorage.setItem("comments", this.showComments);
localStorage.setItem("minimizeDescription", this.minimizeDescription);

View file

@ -3,9 +3,9 @@
<form class="uk-panel uk-panel-box">
<div class="uk-form-row">
<input
v-model="username"
class="uk-width-1-1 uk-form-large uk-input uk-width-auto"
type="text"
v-model="username"
autocomplete="username"
:placeholder="$t('login.username')"
:aria-label="$t('login.username')"
@ -13,9 +13,9 @@
</div>
<div class="uk-form-row">
<input
v-model="password"
class="uk-width-1-1 uk-form-large uk-input uk-width-auto"
type="password"
v-model="password"
autocomplete="password"
:placeholder="$t('login.password')"
:aria-label="$t('login.password')"
@ -26,7 +26,8 @@
class="uk-width-1-1 uk-button uk-button-primary uk-button-large uk-width-auto"
style="background: #222"
@click="register"
> {{ $t("titles.register") }}</a
>
{{ $t("titles.register") }}</a
>
</div>
</form>

View file

@ -3,16 +3,18 @@
{{ $route.query.search_query }}
</h1>
<label for="ddlSearchFilters"><b>{{ $t("actions.filter") }}: </b></label>
<label for="ddlSearchFilters"
><b>{{ $t("actions.filter") }}: </b></label
>
<select
id="ddlSearchFilters"
v-model="selectedFilter"
default="all"
class="uk-select uk-width-auto"
style="height: 100%"
v-model="selectedFilter"
@change="updateResults()"
>
<option v-bind:key="filter" v-for="filter in availableFilters" v-bind:value="filter">
<option v-for="filter in availableFilters" :key="filter" :value="filter">
{{ filter.replace("_", " ") }}
</option>
</select>
@ -21,16 +23,16 @@
<div v-if="results" class="uk-grid-xl" uk-grid="parallax: 0">
<div
v-for="result in results.items"
:key="result.url"
:style="[{ background: backgroundColor }]"
class="uk-width-1-2 uk-width-1-3@s uk-width-1-4@m uk-width-1-5@l uk-width-1-6@xl"
v-bind:key="result.url"
v-for="result in results.items"
>
<VideoItem v-if="shouldUseVideoItem(result)" :video="result" height="94" width="168" />
<div class="uk-text-secondary" v-if="!shouldUseVideoItem(result)">
<router-link class="uk-text-emphasis" v-bind:to="result.url">
<div v-if="!shouldUseVideoItem(result)" class="uk-text-secondary">
<router-link class="uk-text-emphasis" :to="result.url">
<div class="uk-position-relative">
<img style="width: 100%" v-bind:src="result.thumbnail" loading="lazy" />
<img style="width: 100%" :src="result.thumbnail" loading="lazy" />
</div>
<p>
{{ result.name }}&thinsp;<font-awesome-icon
@ -40,7 +42,7 @@
</p>
</router-link>
<p v-if="result.description">{{ result.description }}</p>
<router-link class="uk-link-muted" v-if="result.uploaderUrl" v-bind:to="result.uploaderUrl">
<router-link v-if="result.uploaderUrl" class="uk-link-muted" :to="result.uploaderUrl">
<p>
{{ result.uploader }}&thinsp;<font-awesome-icon
v-if="result.uploaderVerified"
@ -64,6 +66,9 @@
import VideoItem from "@/components/VideoItem.vue";
export default {
components: {
VideoItem,
},
data() {
return {
results: null,
@ -123,8 +128,5 @@ export default {
return item.title;
},
},
components: {
VideoItem,
},
};
</script>

View file

@ -8,9 +8,9 @@
v-for="(suggestion, i) in searchSuggestions"
:key="i"
:style="[selected === i ? { background: secondaryForegroundColor } : {}]"
class="uk-margin-remove suggestion"
@mouseover="onMouseOver(i)"
@mousedown.stop="onClick(i)"
class="uk-margin-remove suggestion"
>
{{ suggestion }}
</li>
@ -21,8 +21,9 @@
<script>
export default {
props: {
searchText: String,
searchText: { type: String, default: "" },
},
emits: ["searchchange"],
data() {
return {
selected: 0,

View file

@ -1,7 +1,6 @@
<template>
<h1 class="uk-text-bold uk-text-center">{{ $t("titles.subscriptions") }}</h1>
<div style="text-align: center">
<button
v-if="authenticated"
@ -16,35 +15,37 @@
<button
v-if="authenticated"
@click="exportHandler"
class="uk-button uk-button-small"
style="background: #222; color: white"
type="button"
@click="exportHandler"
>
{{ $t("actions.export_to_json") }}
</button>
</div>
<hr />
<hr />
<div :key="subscription.url" v-for="subscription in subscriptions" style="text-align: center;">
<div class="uk-text-primary" :style="[{ background: backgroundColor }]">
<a :href="subscription.url">
<img :src="subscription.avatar" class="uk-margin-small-right uk-border-circle" width="96" height="96" />
<span class="uk-text-large" style="width: 30rem; display: inline-block; text-align: center; margin-left: 6rem">{{ subscription.name }}</span>
</a>
<button
class="uk-button uk-button-large"
style="background: #222; margin-left: 0.5rem; width: 185px"
type="button"
@click="handleButton(subscription)"
<div v-for="subscription in subscriptions" :key="subscription.url" style="text-align: center;">
<div class="uk-text-primary" :style="[{ background: backgroundColor }]">
<a :href="subscription.url">
<img :src="subscription.avatar" class="uk-margin-small-right uk-border-circle" width="96" height="96" />
<span
class="uk-text-large"
style="width: 30rem; display: inline-block; text-align: center; margin-left: 6rem"
>{{ subscription.name }}</span
>
{{ subscription.subscribed ? $t("actions.unsubscribe") : $t("actions.subscribe") }}
</button>
</div>
<br />
</a>
<button
class="uk-button uk-button-large"
style="background: #222; margin-left: 0.5rem; width: 185px"
type="button"
@click="handleButton(subscription)"
>
{{ subscription.subscribed ? $t("actions.unsubscribe") : $t("actions.subscribe") }}
</button>
</div>
<br />
</div>
<br />
</template>

View file

@ -1,14 +1,14 @@
<template>
<h1 class="uk-text-bold uk-text-center" v-t="'titles.trending'" />
<h1 v-t="'titles.trending'" class="uk-text-bold uk-text-center" />
<hr />
<div class="uk-grid-xl" uk-grid="parallax: 0">
<div
v-for="video in videos"
:key="video.url"
:style="[{ background: backgroundColor }]"
class="uk-width-1-2 uk-width-1-3@s uk-width-1-4@m uk-width-1-5@l uk-width-1-6@xl"
v-bind:key="video.url"
v-for="video in videos"
>
<VideoItem :video="video" height="118" width="210" />
</div>
@ -19,6 +19,9 @@
import VideoItem from "@/components/VideoItem.vue";
export default {
components: {
VideoItem,
},
data() {
return {
videos: [],
@ -43,8 +46,5 @@ export default {
});
},
},
components: {
VideoItem,
},
};
</script>