mirror of
				https://github.com/TeamPiped/Piped.git
				synced 2024-08-14 23:57:27 +00:00 
			
		
		
		
	Fix Visual Bugs
This commit is contained in:
		
							parent
							
								
									240c419823
								
							
						
					
					
						commit
						941d974503
					
				
					 21 changed files with 437 additions and 761 deletions
				
			
		
							
								
								
									
										22
									
								
								src/App.vue
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								src/App.vue
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,18 +1,22 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <div>
 | 
			
		||||
    <NavBar />
 | 
			
		||||
 | 
			
		||||
    <div class="flex-1">
 | 
			
		||||
        <router-view v-slot="{ Component }">
 | 
			
		||||
            <keep-alive :max="5">
 | 
			
		||||
                <component :is="Component" :key="$route.fullPath" />
 | 
			
		||||
            </keep-alive>
 | 
			
		||||
        </router-view>
 | 
			
		||||
 | 
			
		||||
        <FooterComponent />
 | 
			
		||||
    </div>
 | 
			
		||||
    <FooterComponent />
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
#app {
 | 
			
		||||
    min-height: calc(var(--efy_100vh) - var(--efy_gap2));
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*Radius*/
 | 
			
		||||
input,
 | 
			
		||||
.btn,
 | 
			
		||||
| 
						 | 
				
			
			@ -32,8 +36,7 @@ video {
 | 
			
		|||
    border-radius: var(--efy_radius) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*Radius 0*/
 | 
			
		||||
.video-grid img {
 | 
			
		||||
.video-card .thumbnail {
 | 
			
		||||
    border-radius: var(--efy_radius) var(--efy_radius) 0 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -61,14 +64,15 @@ video {
 | 
			
		|||
    display: -webkit-box;
 | 
			
		||||
    -webkit-line-clamp: 2;
 | 
			
		||||
    -webkit-box-orient: vertical;
 | 
			
		||||
    margin: 0 0 5rem 0;
 | 
			
		||||
    padding: 0 10rem 5rem 10rem;
 | 
			
		||||
    line-height: 22rem;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
.pp-video-card-buttons {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-wrap: wrap;
 | 
			
		||||
    gap: var(--efy_gap0);
 | 
			
		||||
    margin: 5rem 15rem 15rem 15rem;
 | 
			
		||||
    margin: 5rem 10rem 10rem 10rem;
 | 
			
		||||
}
 | 
			
		||||
.pp-video-card-buttons :is(a, button) {
 | 
			
		||||
    padding: 4rem 8rem;
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +117,7 @@ video {
 | 
			
		|||
    gap: var(--efy_gap0);
 | 
			
		||||
    place-items: center;
 | 
			
		||||
    background: transparent;
 | 
			
		||||
    margin: var(--efy_gap0) 0 0;
 | 
			
		||||
    margin: var(--efy_gap0) 0 var(--efy_gap0) var(--efy_gap0);
 | 
			
		||||
    width: fit-content;
 | 
			
		||||
}
 | 
			
		||||
.pp-video-card-channel > a {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <ErrorHandler v-if="channel && channel.error" :message="channel.message" :error="channel.error" />
 | 
			
		||||
    <div v-if="channel" v-show="!channel.error">
 | 
			
		||||
    <div v-if="channel" v-show="!channel.error" class="mt-[15rem]">
 | 
			
		||||
        <LoadingIndicatorPage :show-content="channel != null && !channel.error">
 | 
			
		||||
            <img v-if="channel.bannerUrl" :src="channel.bannerUrl" class="w-full pb-1.5" loading="lazy" />
 | 
			
		||||
            <img v-if="channel.bannerUrl" :src="channel.bannerUrl" class="w-full efy_shadow_trans" loading="lazy" />
 | 
			
		||||
            <div class="pp-channel-page-author flex">
 | 
			
		||||
                <img height="48" width="48" class="m-1" :src="channel.avatarUrl" />
 | 
			
		||||
                <img height="48" width="48" class="efy_shadow_trans" :src="channel.avatarUrl" />
 | 
			
		||||
                <h5 v-text="channel.name" />
 | 
			
		||||
                <font-awesome-icon v-if="channel.verified" class="ml-1.5" icon="check" />
 | 
			
		||||
            </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +71,7 @@
 | 
			
		|||
}
 | 
			
		||||
.pp-channel-tabs :is(button, [role="button"]) {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    border: 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +1,15 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <!-- desktop view -->
 | 
			
		||||
    <div v-if="!mobileLayout" class="pp-chapters flex-col overflow-y-scroll max-h-75vh min-h-64 lt-lg:hidden">
 | 
			
		||||
        <h6 aria-label="chapters" title="chapters" class="efy_trans_filter">
 | 
			
		||||
    <div v-if="!mobileLayout" class="pp-chapters flex-col max-h-75vh min-h-64 lt-lg:hidden">
 | 
			
		||||
        <h6 aria-label="chapters" title="chapters" class="efy_trans_filter efy_shadow_trans">
 | 
			
		||||
            {{ $t("video.chapters") }} - {{ chapters.length }}
 | 
			
		||||
        </h6>
 | 
			
		||||
        <div
 | 
			
		||||
            v-for="(chapter, index) in chapters"
 | 
			
		||||
            :key="chapter.start"
 | 
			
		||||
            class="chapter efy_anim_pulse efy_trans_filter"
 | 
			
		||||
            :class="{ 'pp-chapter-active': isCurrentChapter(index) }"
 | 
			
		||||
            class="chapter efy_anim_pulse"
 | 
			
		||||
            :class="isCurrentChapter(index) ? 'pp-chapter-active' : 'efy_shadow_trans efy_trans_filter'"
 | 
			
		||||
            :role="isCurrentChapter(index) ? 'button' : ''"
 | 
			
		||||
            @click="$emit('seek', chapter.start)"
 | 
			
		||||
        >
 | 
			
		||||
            <div class="flex">
 | 
			
		||||
| 
						 | 
				
			
			@ -77,10 +78,37 @@ defineEmits(["seek"]);
 | 
			
		|||
.text-truncate {
 | 
			
		||||
    @apply truncate overflow-hidden inline-block w-10em;
 | 
			
		||||
}
 | 
			
		||||
.pp-chapters {
 | 
			
		||||
    margin: -15rem 0 0 0;
 | 
			
		||||
    padding: var(--efy_gap);
 | 
			
		||||
    max-width: 400rem;
 | 
			
		||||
    gap: var(--efy_gap0);
 | 
			
		||||
    border-radius: var(--efy_radius);
 | 
			
		||||
    overflow: auto;
 | 
			
		||||
}
 | 
			
		||||
.pp-chapters .chapter {
 | 
			
		||||
    padding: 10rem;
 | 
			
		||||
    border-radius: var(--efy_radius);
 | 
			
		||||
    border: var(--efy_border);
 | 
			
		||||
}
 | 
			
		||||
.pp-chapters [title="chapters"] {
 | 
			
		||||
    padding: 5rem 10rem;
 | 
			
		||||
    border-radius: var(--efy_radius);
 | 
			
		||||
    border: var(--efy_border);
 | 
			
		||||
}
 | 
			
		||||
.pp-chapters .chapter .flex {
 | 
			
		||||
    gap: 0 15rem;
 | 
			
		||||
}
 | 
			
		||||
.pp-chapters.pp-mobile {
 | 
			
		||||
    margin: 15rem 0 0 0;
 | 
			
		||||
    max-width: 100%;
 | 
			
		||||
}
 | 
			
		||||
.pp-chapter-active,
 | 
			
		||||
.pp-chapters .chapter:hover {
 | 
			
		||||
    background: var(--efy_color);
 | 
			
		||||
    background-clip: padding-box;
 | 
			
		||||
    color: var(--efy_text2);
 | 
			
		||||
    border: 0 !important;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <hr />
 | 
			
		||||
    <div class="flex flex-wrap align-center" style="place-content: space-between">
 | 
			
		||||
    <div class="flex flex-wrap align-center" style="place-content: space-between; gap: var(--efy_gap0)">
 | 
			
		||||
        <span class="buttons flex" style="gap: var(--efy_gap0)">
 | 
			
		||||
            <router-link role="button" to="/subscriptions">Subscriptions</router-link>
 | 
			
		||||
            <a :href="getRssUrl" role="button" class="pp-square">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <footer class="efy_trans_filter">
 | 
			
		||||
    <footer class="efy_trans_filter efy_shadow_trans efy_shadow_button_off">
 | 
			
		||||
        <a aria-label="GitHub" href="https://github.com/TeamPiped/Piped" target="_blank">
 | 
			
		||||
            <font-awesome-icon :icon="['fab', 'github']" />
 | 
			
		||||
            <span v-t="'actions.source_code'" />
 | 
			
		||||
| 
						 | 
				
			
			@ -58,12 +58,13 @@ footer {
 | 
			
		|||
    padding: 15rem 5rem;
 | 
			
		||||
    border: var(--efy_border);
 | 
			
		||||
}
 | 
			
		||||
footer > a {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
footer a {
 | 
			
		||||
    color: var(--efy_text) !important;
 | 
			
		||||
    -webkit-text-fill-color: var(--efy_text) !important;
 | 
			
		||||
    background: transparent !important;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    gap: 8rem;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,19 +1,21 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <div class="flex place-items-center">
 | 
			
		||||
        <div class="flex flex-col gap-2 md:flex-row md:items-center">
 | 
			
		||||
            <button v-t="'actions.clear_history'" class="btn" @click="clearHistory" />
 | 
			
		||||
 | 
			
		||||
            <button v-t="'actions.export_to_json'" class="btn" @click="exportHistory" />
 | 
			
		||||
 | 
			
		||||
            <div class="ml-auto flex items-center gap-1">
 | 
			
		||||
                <SortingSelector by-key="watchedAt" @apply="order => videos.sort(order)" />
 | 
			
		||||
            </div>
 | 
			
		||||
    <hr />
 | 
			
		||||
    <div class="flex flex-wrap items-center place-content-between" style="gap: var(--efy_gap0)">
 | 
			
		||||
        <div class="flex" style="gap: var(--efy_gap0)">
 | 
			
		||||
            <button v-t="'actions.clear_history'" class="m-0" @click="clearHistory" />
 | 
			
		||||
            <button v-t="'actions.export_to_json'" class="m-0" @click="exportHistory" />
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="ml-4 flex items-center">
 | 
			
		||||
        <div class="flex flex-wrap items-center" style="gap: var(--efy_gap0)">
 | 
			
		||||
            <div efy_select class="flex flex-wrap" style="gap: var(--efy_gap0)">
 | 
			
		||||
                <input id="autoDelete" v-model="autoDeleteHistory" type="checkbox" @change="onChange" />
 | 
			
		||||
            <label v-t="'actions.delete_automatically'" class="ml-2" for="autoDelete" />
 | 
			
		||||
            <select v-model="autoDeleteDelayHours" class="select ml-3 pl-3" @change="onChange">
 | 
			
		||||
                <label v-t="'actions.delete_automatically'" style="margin: 0" for="autoDelete" />
 | 
			
		||||
                <select
 | 
			
		||||
                    v-model="autoDeleteDelayHours"
 | 
			
		||||
                    class="w-auto"
 | 
			
		||||
                    style="margin: 0 var(--efy_gap0) 0 0"
 | 
			
		||||
                    @change="onChange"
 | 
			
		||||
                >
 | 
			
		||||
                    <option v-t="{ path: 'info.hours', args: { amount: '1' } }" value="1" />
 | 
			
		||||
                    <option v-t="{ path: 'info.hours', args: { amount: '3' } }" value="3" />
 | 
			
		||||
                    <option v-t="{ path: 'info.hours', args: { amount: '6' } }" value="6" />
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +28,8 @@
 | 
			
		|||
                    <option v-t="{ path: 'info.months', args: { amount: '2' } }" value="1344" />
 | 
			
		||||
                </select>
 | 
			
		||||
            </div>
 | 
			
		||||
            <SortingSelector by-key="watchedAt" @apply="order => videos.sort(order)" style="gap: 0" />
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <hr />
 | 
			
		||||
| 
						 | 
				
			
			@ -33,8 +37,6 @@
 | 
			
		|||
    <div class="video-grid">
 | 
			
		||||
        <VideoItem v-for="video in videos" :key="video.url" :item="video" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <br />
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <hr />
 | 
			
		||||
    <div>
 | 
			
		||||
        <form style="display: grid; gap: 15rem">
 | 
			
		||||
            <div>
 | 
			
		||||
| 
						 | 
				
			
			@ -11,9 +12,7 @@
 | 
			
		|||
                <input v-model="override" id="import-override" type="checkbox" />
 | 
			
		||||
                <label for="import-override">Override</label>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div>
 | 
			
		||||
                <a class="btn w-auto" @click="handleImport">Import</a>
 | 
			
		||||
            </div>
 | 
			
		||||
            <a class="btn w-auto" @click="handleImport" role="button" style="margin: 0">Import</a>
 | 
			
		||||
        </form>
 | 
			
		||||
        <br />
 | 
			
		||||
        <strong>Importing Subscriptions from YouTube</strong>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,13 +121,13 @@
 | 
			
		|||
 | 
			
		||||
<style>
 | 
			
		||||
.pp-nav {
 | 
			
		||||
    margin-bottom: 15rem;
 | 
			
		||||
    gap: 15rem;
 | 
			
		||||
}
 | 
			
		||||
.pp-nav > .pp-logo > a {
 | 
			
		||||
    font-size: 25rem;
 | 
			
		||||
    font-family: "nunito";
 | 
			
		||||
    background: transparent;
 | 
			
		||||
    margin-left: 5rem;
 | 
			
		||||
}
 | 
			
		||||
.pp-nav > div input {
 | 
			
		||||
    margin: 0 !important;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,30 +1,36 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <div class="flex flex-col flex-justify-between">
 | 
			
		||||
    <div class="video-card flex flex-col flex-justify-between efy_shadow_trans">
 | 
			
		||||
        <router-link :to="props.item.url">
 | 
			
		||||
            <div class="relative">
 | 
			
		||||
                <img class="w-full" :src="props.item.thumbnail" loading="lazy" />
 | 
			
		||||
                <img class="thumbnail" :src="props.item.thumbnail" loading="lazy" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <p>
 | 
			
		||||
                <span v-text="props.item.name" />
 | 
			
		||||
                <span v-text="props.item.name" class="pp-video-card-title" />
 | 
			
		||||
                <font-awesome-icon v-if="props.item.verified" class="ml-1.5" icon="check" />
 | 
			
		||||
            </p>
 | 
			
		||||
        </router-link>
 | 
			
		||||
        <p v-if="props.item.description" v-text="props.item.description" />
 | 
			
		||||
 | 
			
		||||
        <router-link v-if="props.item.uploaderUrl" class="link" :to="props.item.uploaderUrl">
 | 
			
		||||
            <p>
 | 
			
		||||
                <span v-text="props.item.uploaderName" />
 | 
			
		||||
                <font-awesome-icon v-if="props.item.uploaderVerified" class="ml-1.5" icon="check" />
 | 
			
		||||
            </p>
 | 
			
		||||
        <div class="pp-video-card-buttons">
 | 
			
		||||
            <button
 | 
			
		||||
                v-if="props.item.videos >= 0"
 | 
			
		||||
                v-text="`${props.item.videos} ${$t('video.videos')}`"
 | 
			
		||||
                class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
 | 
			
		||||
            />
 | 
			
		||||
            <router-link
 | 
			
		||||
                v-if="props.item.uploaderUrl && item.uploaderName"
 | 
			
		||||
                :to="props.item.uploaderUrl"
 | 
			
		||||
                :title="props.item.uploaderName"
 | 
			
		||||
                class="pp-video-card-channel"
 | 
			
		||||
                style="padding: 0; flex-grow: 1; background: transparent; border: 0"
 | 
			
		||||
            >
 | 
			
		||||
                <div class="pp-text efy_shadow_trans efy_shadow_button_off flex-grow-1">
 | 
			
		||||
                    <span v-text="props.item.uploaderName" style="max-width: 106rem" />
 | 
			
		||||
                    <font-awesome-icon class="ml-1.5" v-if="item.uploaderVerified" icon="check" />
 | 
			
		||||
                </div>
 | 
			
		||||
            </router-link>
 | 
			
		||||
        <a v-else-if="props.item.uploaderName" class="link" v-text="props.item.uploaderName" />
 | 
			
		||||
 | 
			
		||||
        <template v-if="props.item.videos >= 0">
 | 
			
		||||
            <br v-if="props.item.uploaderName" />
 | 
			
		||||
            <strong v-text="`${props.item.videos} ${$t('video.videos')}`" />
 | 
			
		||||
        </template>
 | 
			
		||||
 | 
			
		||||
        <br />
 | 
			
		||||
            <a v-else-if="props.item.uploaderName" class="pp-video-card-channel" v-text="props.item.uploaderName" />
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,18 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <hr />
 | 
			
		||||
    <div class="flex justify-between">
 | 
			
		||||
        <button v-t="'actions.create_playlist'" class="btn mr-2" @click="onCreatePlaylist" />
 | 
			
		||||
        <div class="flex">
 | 
			
		||||
            <button v-if="playlists.length > 0" v-t="'actions.export_to_json'" @click="exportPlaylists" />
 | 
			
		||||
    <div class="flex justify-between items-center">
 | 
			
		||||
        <button
 | 
			
		||||
            v-t="'actions.create_playlist'"
 | 
			
		||||
            style="height: var(--efy_ratio_width); margin: 0"
 | 
			
		||||
            @click="onCreatePlaylist"
 | 
			
		||||
        />
 | 
			
		||||
        <div class="flex flex-wrap" style="gap: var(--efy_gap0)">
 | 
			
		||||
            <button
 | 
			
		||||
                v-if="playlists.length > 0"
 | 
			
		||||
                v-t="'actions.export_to_json'"
 | 
			
		||||
                @click="exportPlaylists"
 | 
			
		||||
                style="height: var(--efy_ratio_width); margin: 0"
 | 
			
		||||
            />
 | 
			
		||||
            <input
 | 
			
		||||
                id="fileSelector"
 | 
			
		||||
                ref="fileSelector"
 | 
			
		||||
| 
						 | 
				
			
			@ -12,14 +21,15 @@
 | 
			
		|||
                multiple="multiple"
 | 
			
		||||
                @change="importPlaylists"
 | 
			
		||||
            />
 | 
			
		||||
            <label v-t="'actions.import_from_json_csv'" for="fileSelector" class="btn ml-2" role="button" />
 | 
			
		||||
            <label v-t="'actions.import_from_json_csv'" for="fileSelector" class="m-0! font-bold" role="button" />
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr />
 | 
			
		||||
 | 
			
		||||
    <div class="video-grid">
 | 
			
		||||
        <div v-for="playlist in playlists" :key="playlist.id" class="efy_trans_filter">
 | 
			
		||||
        <div v-for="playlist in playlists" :key="playlist.id" class="video-card efy_trans_filter">
 | 
			
		||||
            <router-link :to="`/playlist?list=${playlist.id}`">
 | 
			
		||||
                <img class="w-full" :src="playlist.thumbnail" alt="thumbnail" />
 | 
			
		||||
                <img class="thumbnail" :src="playlist.thumbnail" alt="thumbnail" />
 | 
			
		||||
                <p
 | 
			
		||||
                    style="display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; margin: 0 15rem"
 | 
			
		||||
                    class="flex link"
 | 
			
		||||
| 
						 | 
				
			
			@ -68,32 +78,32 @@
 | 
			
		|||
    </div>
 | 
			
		||||
    <hr />
 | 
			
		||||
 | 
			
		||||
    <h2 v-t="'titles.bookmarks'" class="my-4 font-bold" />
 | 
			
		||||
 | 
			
		||||
    <h5 v-if="bookmarks" v-t="'titles.bookmarks'" class="mb-[15rem]" />
 | 
			
		||||
    <div v-if="bookmarks" class="video-grid">
 | 
			
		||||
        <router-link
 | 
			
		||||
        <div
 | 
			
		||||
            v-for="(playlist, index) in bookmarks"
 | 
			
		||||
            :key="playlist.playlistId"
 | 
			
		||||
            :to="`/playlist?list=${playlist.playlistId}`"
 | 
			
		||||
            class="pp-bookmark video-card efy_trans_filter"
 | 
			
		||||
        >
 | 
			
		||||
            <img class="w-full" :src="playlist.thumbnail" alt="thumbnail" />
 | 
			
		||||
            <div class="relative text-sm">
 | 
			
		||||
                <span class="thumbnail-overlay thumbnail-right" v-text="`${playlist.videos} ${$t('video.videos')}`" />
 | 
			
		||||
                <div class="absolute bottom-100px right-5px z-100 px-5px" @click.prevent="removeBookmark(index)">
 | 
			
		||||
                    <font-awesome-icon class="ml-3" icon="bookmark" />
 | 
			
		||||
            <router-link :to="`/playlist?list=${playlist.playlistId}`">
 | 
			
		||||
                <img class="thumbnail" :src="playlist.thumbnail" alt="thumbnail" />
 | 
			
		||||
                <div class="flex items-center h-[44rem] overflow-hidden">
 | 
			
		||||
                    <p class="pp-video-card-title" :title="playlist.name" v-text="playlist.name" />
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <p
 | 
			
		||||
                style="display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; margin: 0 0 0 10rem"
 | 
			
		||||
                class="link my-2 flex overflow-hidden"
 | 
			
		||||
                :title="playlist.name"
 | 
			
		||||
                v-text="playlist.name"
 | 
			
		||||
            />
 | 
			
		||||
            <a :href="playlist.uploaderUrl" class="flex items-center">
 | 
			
		||||
                <img class="h-32px w-32px rounded-full" :src="playlist.uploaderAvatar" />
 | 
			
		||||
                <span class="ml-3 hover:underline" v-text="playlist.uploader" />
 | 
			
		||||
            </a>
 | 
			
		||||
            </router-link>
 | 
			
		||||
            <div class="pp-video-card-buttons flex gap-15rem">
 | 
			
		||||
                <button @click.prevent="removeBookmark(index)">
 | 
			
		||||
                    <font-awesome-icon class="ml-3" icon="bookmark" />
 | 
			
		||||
                </button>
 | 
			
		||||
                <button v-text="`${playlist.videos} ${$t('video.videos')}`" class="thumbnail-overlay" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <a :href="playlist.uploaderUrl" class="pp-video-card-channel">
 | 
			
		||||
                <img class="w-36rem h-36rem efy_shadow_trans" :src="playlist.uploaderAvatar" width="36" height="36" />
 | 
			
		||||
                <div class="pp-text efy_shadow_trans efy_shadow_button_off">
 | 
			
		||||
                    <span v-text="playlist.uploader" />
 | 
			
		||||
                </div>
 | 
			
		||||
            </a>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,7 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <!--efy-->
 | 
			
		||||
    <div class="pp-pref-cards">
 | 
			
		||||
        <div efy_card="grid">
 | 
			
		||||
            <h2>Quick</h2>
 | 
			
		||||
            <h5>Quick</h5>
 | 
			
		||||
            <label class="pref" for="ddlLanguageSelection">
 | 
			
		||||
                <strong v-t="'actions.language_selection'" />
 | 
			
		||||
                <select
 | 
			
		||||
| 
						 | 
				
			
			@ -86,56 +85,60 @@
 | 
			
		|||
                    </select>
 | 
			
		||||
                </label>
 | 
			
		||||
            </template>
 | 
			
		||||
            <br />
 | 
			
		||||
 | 
			
		||||
            <p v-t="'info.preferences_note'" />
 | 
			
		||||
            <button class="btn" v-t="'actions.reset_preferences'" @click="resetPreferences()" />
 | 
			
		||||
            <button class="btn mx-4" v-t="'actions.backup_preferences'" @click="backupPreferences()" />
 | 
			
		||||
            <label
 | 
			
		||||
                for="fileSelector"
 | 
			
		||||
                class="btn text-center"
 | 
			
		||||
                v-t="'actions.restore_preferences'"
 | 
			
		||||
                @click="restorePreferences()"
 | 
			
		||||
            <div class="pref items-start! flex-col">
 | 
			
		||||
                <strong>Preferences</strong>
 | 
			
		||||
                <div class="flex flex-wrap" style="gap: var(--efy_gap0)">
 | 
			
		||||
                    <button style="height: var(--efy_ratio_width)" @click="showConfirmResetPrefsDialog = true">
 | 
			
		||||
                        Reset
 | 
			
		||||
                    </button>
 | 
			
		||||
                    <button style="height: var(--efy_ratio_width)" @click="backupPreferences()">Backup</button>
 | 
			
		||||
                    <label for="fileSelector" class="btn text-center" role="button" @click="restorePreferences()">
 | 
			
		||||
                        Restore
 | 
			
		||||
                    </label>
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="fileSelector"
 | 
			
		||||
                        ref="fileSelector"
 | 
			
		||||
                        class="hidden"
 | 
			
		||||
                        type="file"
 | 
			
		||||
                        @change="restorePreferences()"
 | 
			
		||||
                    />
 | 
			
		||||
                </div>
 | 
			
		||||
                <p v-t="'info.preferences_note'" />
 | 
			
		||||
                <ConfirmModal
 | 
			
		||||
                    v-if="showConfirmResetPrefsDialog"
 | 
			
		||||
                    :message="$t('actions.confirm_reset_preferences')"
 | 
			
		||||
                    @close="showConfirmResetPrefsDialog = false"
 | 
			
		||||
                    @confirm="resetPreferences()"
 | 
			
		||||
                />
 | 
			
		||||
            </div>
 | 
			
		||||
    <!--master-->
 | 
			
		||||
    <div class="flex">
 | 
			
		||||
        <button @click="$router.go(-1) || $router.push('/')">
 | 
			
		||||
            <font-awesome-icon icon="chevron-left" /><span v-t="'actions.back'" class="ml-1.5" />
 | 
			
		||||
        </button>
 | 
			
		||||
            <!-- options that are visible only when logged in -->
 | 
			
		||||
            <div v-if="authenticated" class="pref items-start! flex-col">
 | 
			
		||||
                <label v-t="'actions.delete_account'" for="txtDeleteAccountPassword" class="font-bold" />
 | 
			
		||||
                <div class="flex flex-wrap" style="gap: var(--efy_gap0)">
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="txtDeleteAccountPassword"
 | 
			
		||||
                        ref="txtDeleteAccountPassword"
 | 
			
		||||
                        v-model="password"
 | 
			
		||||
                        :placeholder="$t('login.password')"
 | 
			
		||||
                        :aria-label="$t('login.password')"
 | 
			
		||||
                        class="input mr-2 w-auto"
 | 
			
		||||
                        type="password"
 | 
			
		||||
                        @keyup.enter="deleteAccount"
 | 
			
		||||
                    />
 | 
			
		||||
                    <button v-t="'actions.delete_account'" class="w-auto" @click="deleteAccount" />
 | 
			
		||||
                </div>
 | 
			
		||||
    <h1 v-t="'titles.preferences'" class="text-center font-bold" />
 | 
			
		||||
    <hr />
 | 
			
		||||
    <label for="ddlTheme" class="pref">
 | 
			
		||||
        <strong v-t="'actions.theme'" />
 | 
			
		||||
        <select id="ddlTheme" v-model="selectedTheme" class="select w-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>
 | 
			
		||||
    </label>
 | 
			
		||||
    <label class="pref" for="ddlLanguageSelection">
 | 
			
		||||
        <strong v-t="'actions.language_selection'" />
 | 
			
		||||
        <select id="ddlLanguageSelection" v-model="selectedLanguage" class="select w-auto" @change="onChange($event)">
 | 
			
		||||
            <option v-for="language in languages" :key="language.code" :value="language.code" v-text="language.name" />
 | 
			
		||||
        </select>
 | 
			
		||||
    </label>
 | 
			
		||||
    <label class="pref" for="ddlCountrySelection">
 | 
			
		||||
        <strong v-t="'actions.country_selection'" />
 | 
			
		||||
        <select id="ddlCountrySelection" v-model="countrySelected" class="select w-50" @change="onChange($event)">
 | 
			
		||||
            <option v-for="country in countryMap" :key="country.code" :value="country.code" v-text="country.name" />
 | 
			
		||||
        </select>
 | 
			
		||||
    </label>
 | 
			
		||||
    <label class="pref" for="ddlDefaultHomepage">
 | 
			
		||||
        <strong v-t="'actions.default_homepage'" />
 | 
			
		||||
        <select id="ddlDefaultHomepage" v-model="defaultHomepage" class="select w-auto" @change="onChange($event)">
 | 
			
		||||
            <option v-t="'titles.trending'" value="trending" />
 | 
			
		||||
            <option v-t="'titles.feed'" value="feed" />
 | 
			
		||||
        </select>
 | 
			
		||||
    </label>
 | 
			
		||||
 | 
			
		||||
    <h2 v-t="'titles.player'" class="text-center" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div v-if="authenticated" class="pref items-start! flex-col" style="border-bottom: var(--efy_border)">
 | 
			
		||||
                <strong>Logout</strong>
 | 
			
		||||
                <div class="flex flex-wrap" style="gap: var(--efy_gap0)">
 | 
			
		||||
                    <button v-t="'actions.logout'" class="w-auto" @click="logout" />
 | 
			
		||||
                    <button v-t="'actions.invalidate_session'" class="w-auto" @click="invalidateSession" />
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div efy_card="grid">
 | 
			
		||||
            <h5 v-t="'titles.player'" />
 | 
			
		||||
            <label class="pref" for="chkAutoPlayVideo">
 | 
			
		||||
                <strong v-t="'actions.autoplay_video'" />
 | 
			
		||||
                <input
 | 
			
		||||
| 
						 | 
				
			
			@ -172,9 +175,19 @@
 | 
			
		|||
            </label>
 | 
			
		||||
            <label class="pref" for="ddlDefaultQuality">
 | 
			
		||||
                <strong v-t="'actions.default_quality'" />
 | 
			
		||||
        <select id="ddlDefaultQuality" v-model="defaultQuality" class="select w-auto" @change="onChange($event)">
 | 
			
		||||
                <select
 | 
			
		||||
                    id="ddlDefaultQuality"
 | 
			
		||||
                    v-model="defaultQuality"
 | 
			
		||||
                    class="select w-auto"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                >
 | 
			
		||||
                    <option v-t="'actions.auto'" value="0" />
 | 
			
		||||
            <option v-for="resolution in resolutions" :key="resolution" :value="resolution" v-text="`${resolution}p`" />
 | 
			
		||||
                    <option
 | 
			
		||||
                        v-for="resolution in resolutions"
 | 
			
		||||
                        :key="resolution"
 | 
			
		||||
                        :value="resolution"
 | 
			
		||||
                        v-text="`${resolution}p`"
 | 
			
		||||
                    />
 | 
			
		||||
                </select>
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="txtBufferingGoal">
 | 
			
		||||
| 
						 | 
				
			
			@ -228,10 +241,15 @@
 | 
			
		|||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <!-- chapters layout on mobile -->
 | 
			
		||||
    <label class="pref lg:invisible" for="chkMinimizeChapters">
 | 
			
		||||
            <label class="pref" for="chkMinimizeChapters">
 | 
			
		||||
                <strong v-t="'actions.chapters_layout_mobile'" />
 | 
			
		||||
 | 
			
		||||
        <select id="ddlDefaultHomepage" v-model="mobileChapterLayout" class="select w-auto" @change="onChange($event)">
 | 
			
		||||
                <select
 | 
			
		||||
                    id="ddlDefaultHomepage"
 | 
			
		||||
                    v-model="mobileChapterLayout"
 | 
			
		||||
                    class="select w-auto"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                >
 | 
			
		||||
                    <option v-t="'video.chapters_horizontal'" value="Horizontal" />
 | 
			
		||||
                    <option v-t="'video.chapters_vertical'" value="Vertical" />
 | 
			
		||||
                </select>
 | 
			
		||||
| 
						 | 
				
			
			@ -276,299 +294,6 @@
 | 
			
		|||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
    <label v-if="watchHistory" class="pref" for="chkHideWatched">
 | 
			
		||||
        <strong v-t="'actions.hide_watched'" />
 | 
			
		||||
        <input id="chkHideWatched" v-model="hideWatched" class="checkbox" type="checkbox" @change="onChange($event)" />
 | 
			
		||||
    </label>
 | 
			
		||||
    <label class="pref" for="ddlEnabledCodecs">
 | 
			
		||||
        <strong v-t="'actions.enabled_codecs'" />
 | 
			
		||||
        <select
 | 
			
		||||
            id="ddlEnabledCodecs"
 | 
			
		||||
            v-model="enabledCodecs"
 | 
			
		||||
            class="select h-auto w-auto"
 | 
			
		||||
            multiple
 | 
			
		||||
            @change="onChange($event)"
 | 
			
		||||
        >
 | 
			
		||||
            <option value="av1">AV1</option>
 | 
			
		||||
            <option value="vp9">VP9</option>
 | 
			
		||||
            <option value="avc">AVC (h.264)</option>
 | 
			
		||||
        </select>
 | 
			
		||||
    </label>
 | 
			
		||||
    <label class="pref" for="chkDisableLBRY">
 | 
			
		||||
        <strong v-t="'actions.disable_lbry'" />
 | 
			
		||||
        <input id="chkDisableLBRY" v-model="disableLBRY" class="checkbox" type="checkbox" @change="onChange($event)" />
 | 
			
		||||
    </label>
 | 
			
		||||
    <label class="pref" for="chkEnableLBRYProxy">
 | 
			
		||||
        <strong v-t="'actions.enable_lbry_proxy'" />
 | 
			
		||||
        <input
 | 
			
		||||
            id="chkEnableLBRYProxy"
 | 
			
		||||
            v-model="proxyLBRY"
 | 
			
		||||
            class="checkbox"
 | 
			
		||||
            type="checkbox"
 | 
			
		||||
            @change="onChange($event)"
 | 
			
		||||
        />
 | 
			
		||||
    </label>
 | 
			
		||||
 | 
			
		||||
    <h2 class="text-center">SponsorBlock</h2>
 | 
			
		||||
    <p class="text-center">
 | 
			
		||||
        <span v-t="'actions.uses_api_from'" /><a class="link" href="https://sponsor.ajay.app/">sponsor.ajay.app</a>
 | 
			
		||||
    </p>
 | 
			
		||||
    <label class="pref" for="chkEnableSponsorblock">
 | 
			
		||||
        <strong v-t="'actions.enable_sponsorblock'" />
 | 
			
		||||
        <input
 | 
			
		||||
            id="chkEnableSponsorblock"
 | 
			
		||||
            v-model="sponsorBlock"
 | 
			
		||||
            class="checkbox"
 | 
			
		||||
            type="checkbox"
 | 
			
		||||
            @change="onChange($event)"
 | 
			
		||||
        />
 | 
			
		||||
    </label>
 | 
			
		||||
    <div v-if="sponsorBlock">
 | 
			
		||||
        <label v-for="[name, item] in skipOptions" :key="name" class="pref" :for="'ddlSkip_' + name">
 | 
			
		||||
            <strong v-t="item.label" />
 | 
			
		||||
            <select :id="'ddlSkip_' + name" v-model="item.value" class="select w-auto" @change="onChange($event)">
 | 
			
		||||
                <option v-t="'actions.no'" value="no" />
 | 
			
		||||
                <option v-t="'actions.skip_button_only'" value="button" />
 | 
			
		||||
                <option v-t="'actions.skip_automatically'" value="auto" />
 | 
			
		||||
            </select>
 | 
			
		||||
        </label>
 | 
			
		||||
        <label class="pref" for="chkShowMarkers">
 | 
			
		||||
            <strong v-t="'actions.show_markers'" />
 | 
			
		||||
            <input
 | 
			
		||||
                id="chkShowMarkers"
 | 
			
		||||
                v-model="showMarkers"
 | 
			
		||||
                class="checkbox"
 | 
			
		||||
                type="checkbox"
 | 
			
		||||
                @change="onChange($event)"
 | 
			
		||||
            />
 | 
			
		||||
        </label>
 | 
			
		||||
        <label class="pref" for="txtMinSegmentLength">
 | 
			
		||||
            <strong v-t="'actions.min_segment_length'" />
 | 
			
		||||
            <input
 | 
			
		||||
                id="txtMinSegmentLength"
 | 
			
		||||
                v-model="minSegmentLength"
 | 
			
		||||
                class="input w-24"
 | 
			
		||||
                type="text"
 | 
			
		||||
                @change="onChange($event)"
 | 
			
		||||
            />
 | 
			
		||||
        </label>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <h2 v-t="'titles.dearrow'" class="text-center" />
 | 
			
		||||
    <p class="text-center">
 | 
			
		||||
        <span v-t="'actions.uses_api_from'" /><a class="link" href="https://sponsor.ajay.app/">sponsor.ajay.app</a>
 | 
			
		||||
    </p>
 | 
			
		||||
    <label class="pref" for="chkDeArrow">
 | 
			
		||||
        <strong v-t="'actions.enable_dearrow'" />
 | 
			
		||||
        <input id="chkDeArrow" v-model="dearrow" class="checkbox" type="checkbox" @change="onChange($event)" />
 | 
			
		||||
    </label>
 | 
			
		||||
 | 
			
		||||
    <h2 v-t="'titles.instance'" class="text-center" />
 | 
			
		||||
    <label class="pref" for="ddlInstanceSelection">
 | 
			
		||||
        <strong v-text="`${$t('actions.instance_selection')}:`" />
 | 
			
		||||
        <select id="ddlInstanceSelection" v-model="selectedInstance" class="select w-auto" @change="onChange($event)">
 | 
			
		||||
            <option
 | 
			
		||||
                v-for="instance in instances"
 | 
			
		||||
                :key="instance.name"
 | 
			
		||||
                :value="instance.api_url"
 | 
			
		||||
                v-text="instance.name"
 | 
			
		||||
            />
 | 
			
		||||
        </select>
 | 
			
		||||
    </label>
 | 
			
		||||
    <label class="pref" for="chkAuthInstance">
 | 
			
		||||
        <strong v-text="`${$t('actions.different_auth_instance')}:`" />
 | 
			
		||||
        <input
 | 
			
		||||
            id="chkAuthInstance"
 | 
			
		||||
            v-model="authInstance"
 | 
			
		||||
            class="checkbox"
 | 
			
		||||
            type="checkbox"
 | 
			
		||||
            @change="onChange($event)"
 | 
			
		||||
        />
 | 
			
		||||
    </label>
 | 
			
		||||
    <template v-if="authInstance">
 | 
			
		||||
        <label class="pref" for="ddlAuthInstanceSelection">
 | 
			
		||||
            <strong v-text="`${$t('actions.instance_auth_selection')}:`" />
 | 
			
		||||
            <select
 | 
			
		||||
                id="ddlAuthInstanceSelection"
 | 
			
		||||
                v-model="selectedAuthInstance"
 | 
			
		||||
                class="select w-auto"
 | 
			
		||||
                @change="onChange($event)"
 | 
			
		||||
            >
 | 
			
		||||
                <option
 | 
			
		||||
                    v-for="instance in instances"
 | 
			
		||||
                    :key="instance.name"
 | 
			
		||||
                    :value="instance.api_url"
 | 
			
		||||
                    v-text="instance.name"
 | 
			
		||||
                />
 | 
			
		||||
            </select>
 | 
			
		||||
        </label>
 | 
			
		||||
    </template>
 | 
			
		||||
    <br />
 | 
			
		||||
 | 
			
		||||
    <!-- options that are visible only when logged in -->
 | 
			
		||||
    <div v-if="authenticated">
 | 
			
		||||
        <h2 v-t="'titles.account'" class="text-center"></h2>
 | 
			
		||||
        <label class="pref" for="txtDeleteAccountPassword">
 | 
			
		||||
            <strong v-t="'actions.delete_account'" />
 | 
			
		||||
            <div class="flex items-center">
 | 
			
		||||
                <input
 | 
			
		||||
                    id="txtDeleteAccountPassword"
 | 
			
		||||
                    ref="txtDeleteAccountPassword"
 | 
			
		||||
                    v-model="password"
 | 
			
		||||
                    :placeholder="$t('login.password')"
 | 
			
		||||
                    :aria-label="$t('login.password')"
 | 
			
		||||
                    class="input mr-2 w-auto"
 | 
			
		||||
                    type="password"
 | 
			
		||||
                    @keyup.enter="deleteAccount"
 | 
			
		||||
                />
 | 
			
		||||
                <a v-t="'actions.delete_account'" class="btn w-auto" @click="deleteAccount" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </label>
 | 
			
		||||
        <div class="pref">
 | 
			
		||||
            <a v-t="'actions.logout'" class="btn w-auto" @click="logout" />
 | 
			
		||||
            <a
 | 
			
		||||
                v-t="'actions.invalidate_session'"
 | 
			
		||||
                class="btn w-auto"
 | 
			
		||||
                style="margin-left: 0.5em"
 | 
			
		||||
                @click="invalidateSession"
 | 
			
		||||
            />
 | 
			
		||||
            <!--masterend-->
 | 
			
		||||
            <input class="hidden" id="fileSelector" ref="fileSelector" type="file" @change="restorePreferences()" />
 | 
			
		||||
 | 
			
		||||
            <!-- options that are visible only when logged in -->
 | 
			
		||||
            <div v-if="this.authenticated">
 | 
			
		||||
                <label class="pp-delete-account pref" for="txtDeleteAccountPassword" efy_card="grid">
 | 
			
		||||
                    <h6 v-t="'actions.delete_account'" />
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="txtDeleteAccountPassword"
 | 
			
		||||
                        ref="txtDeleteAccountPassword"
 | 
			
		||||
                        v-model="password"
 | 
			
		||||
                        v-on:keyup.enter="deleteAccount"
 | 
			
		||||
                        :placeholder="$t('login.password')"
 | 
			
		||||
                        :aria-label="$t('login.password')"
 | 
			
		||||
                        class="input w-auto mr-2"
 | 
			
		||||
                        type="password"
 | 
			
		||||
                    />
 | 
			
		||||
                    <a class="btn w-full" @click="deleteAccount" v-t="'actions.delete_account'" />
 | 
			
		||||
                </label>
 | 
			
		||||
                <button class="btn w-full" @click="logout" v-t="'actions.logout'" />
 | 
			
		||||
                <button class="btn w-full" @click="invalidateSession" v-t="'actions.invalidate_session'" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div efy_card="grid">
 | 
			
		||||
            <h2 v-t="'titles.player'" />
 | 
			
		||||
            <label class="pref" for="chkAutoPlayVideo">
 | 
			
		||||
                <strong v-t="'actions.autoplay_video'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkAutoPlayVideo"
 | 
			
		||||
                    v-model="autoPlayVideo"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkAudioOnly">
 | 
			
		||||
                <strong v-t="'actions.audio_only'" />
 | 
			
		||||
                <input id="chkAudioOnly" v-model="listen" class="checkbox" type="checkbox" @change="onChange($event)" />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="ddlDefaultQuality">
 | 
			
		||||
                <strong v-t="'actions.default_quality'" />
 | 
			
		||||
                <select
 | 
			
		||||
                    id="ddlDefaultQuality"
 | 
			
		||||
                    v-model="defaultQuality"
 | 
			
		||||
                    class="select w-auto"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                >
 | 
			
		||||
                    <option v-t="'actions.auto'" value="0" />
 | 
			
		||||
                    <option
 | 
			
		||||
                        v-for="resolution in resolutions"
 | 
			
		||||
                        :key="resolution"
 | 
			
		||||
                        :value="resolution"
 | 
			
		||||
                        v-text="`${resolution}p`"
 | 
			
		||||
                    />
 | 
			
		||||
                </select>
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="txtBufferingGoal">
 | 
			
		||||
                <strong v-t="'actions.buffering_goal'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="txtBufferingGoal"
 | 
			
		||||
                    v-model="bufferingGoal"
 | 
			
		||||
                    class="input w-auto"
 | 
			
		||||
                    type="text"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkMinimizeComments">
 | 
			
		||||
                <strong v-t="'actions.minimize_comments_default'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkMinimizeComments"
 | 
			
		||||
                    v-model="minimizeComments"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkMinimizeDescription">
 | 
			
		||||
                <strong v-t="'actions.minimize_description_default'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkMinimizeDescription"
 | 
			
		||||
                    v-model="minimizeDescription"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkMinimizeRecommendations">
 | 
			
		||||
                <strong v-t="'actions.minimize_recommendations_default'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkMinimizeRecommendations"
 | 
			
		||||
                    v-model="minimizeRecommendations"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkMinimizeChapters">
 | 
			
		||||
                <strong v-t="'actions.minimize_chapters_default'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkMinimizeChapters"
 | 
			
		||||
                    v-model="minimizeChapters"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkShowWatchOnYouTube">
 | 
			
		||||
                <strong v-t="'actions.show_watch_on_youtube'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkShowWatchOnYouTube"
 | 
			
		||||
                    v-model="showWatchOnYouTube"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkStoreSearchHistory">
 | 
			
		||||
                <strong v-t="'actions.store_search_history'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkStoreSearchHistory"
 | 
			
		||||
                    v-model="searchHistory"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkStoreWatchHistory">
 | 
			
		||||
                <strong v-t="'actions.store_watch_history'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkStoreWatchHistory"
 | 
			
		||||
                    v-model="watchHistory"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label v-if="watchHistory" class="pref" for="chkHideWatched">
 | 
			
		||||
                <strong v-t="'actions.hide_watched'" />
 | 
			
		||||
                <input
 | 
			
		||||
| 
						 | 
				
			
			@ -584,7 +309,7 @@
 | 
			
		|||
                <select
 | 
			
		||||
                    id="ddlEnabledCodecs"
 | 
			
		||||
                    v-model="enabledCodecs"
 | 
			
		||||
                    class="select w-auto h-auto"
 | 
			
		||||
                    class="select h-auto w-auto"
 | 
			
		||||
                    multiple
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                >
 | 
			
		||||
| 
						 | 
				
			
			@ -616,12 +341,16 @@
 | 
			
		|||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div efy_card="grid">
 | 
			
		||||
            <h2>SponsorBlock</h2>
 | 
			
		||||
            <p>
 | 
			
		||||
            <h5>SponsorBlock + DeArrow</h5>
 | 
			
		||||
            <p class="pref" style="justify-content: unset !important">
 | 
			
		||||
                <span v-t="'actions.uses_api_from'" /><a class="link" href="https://sponsor.ajay.app/"
 | 
			
		||||
                    >sponsor.ajay.app</a
 | 
			
		||||
                >
 | 
			
		||||
            </p>
 | 
			
		||||
            <label class="pref" for="chkDeArrow">
 | 
			
		||||
                <strong v-t="'actions.enable_dearrow'" />
 | 
			
		||||
                <input id="chkDeArrow" v-model="dearrow" class="checkbox" type="checkbox" @change="onChange($event)" />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkEnableSponsorblock">
 | 
			
		||||
                <strong v-t="'actions.enable_sponsorblock'" />
 | 
			
		||||
                <input
 | 
			
		||||
| 
						 | 
				
			
			@ -632,95 +361,19 @@
 | 
			
		|||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkSkipSponsors">
 | 
			
		||||
                <strong v-t="'actions.skip_sponsors'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkSkipSponsors"
 | 
			
		||||
                    v-model="skipSponsor"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
            <div v-if="sponsorBlock">
 | 
			
		||||
                <label v-for="[name, item] in skipOptions" :key="name" class="pref" :for="'ddlSkip_' + name">
 | 
			
		||||
                    <strong v-t="item.label" />
 | 
			
		||||
                    <select
 | 
			
		||||
                        :id="'ddlSkip_' + name"
 | 
			
		||||
                        v-model="item.value"
 | 
			
		||||
                        class="select w-auto"
 | 
			
		||||
                        @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkSkipIntro">
 | 
			
		||||
                <strong v-t="'actions.skip_intro'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkSkipIntro"
 | 
			
		||||
                    v-model="skipIntro"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkSkipOutro">
 | 
			
		||||
                <strong v-t="'actions.skip_outro'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkSkipOutro"
 | 
			
		||||
                    v-model="skipOutro"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkSkipPreview">
 | 
			
		||||
                <strong v-t="'actions.skip_preview'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkSkipPreview"
 | 
			
		||||
                    v-model="skipPreview"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkSkipInteraction">
 | 
			
		||||
                <strong v-t="'actions.skip_interaction'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkSkipInteraction"
 | 
			
		||||
                    v-model="skipInteraction"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkSkipSelfPromo">
 | 
			
		||||
                <strong v-t="'actions.skip_self_promo'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkSkipSelfPromo"
 | 
			
		||||
                    v-model="skipSelfPromo"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkSkipNonMusic">
 | 
			
		||||
                <strong v-t="'actions.skip_non_music'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkSkipNonMusic"
 | 
			
		||||
                    v-model="skipMusicOffTopic"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkSkipHighlight">
 | 
			
		||||
                <strong v-t="'actions.skip_highlight'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkSkipHighlight"
 | 
			
		||||
                    v-model="skipHighlight"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
            </label>
 | 
			
		||||
            <label class="pref" for="chkSkipFiller">
 | 
			
		||||
                <strong v-t="'actions.skip_filler_tangent'" />
 | 
			
		||||
                <input
 | 
			
		||||
                    id="chkSkipFiller"
 | 
			
		||||
                    v-model="skipFiller"
 | 
			
		||||
                    class="checkbox"
 | 
			
		||||
                    type="checkbox"
 | 
			
		||||
                    @change="onChange($event)"
 | 
			
		||||
                />
 | 
			
		||||
                    >
 | 
			
		||||
                        <option v-t="'actions.no'" value="no" />
 | 
			
		||||
                        <option v-t="'actions.skip_button_only'" value="button" />
 | 
			
		||||
                        <option v-t="'actions.skip_automatically'" value="auto" />
 | 
			
		||||
                    </select>
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="pref" for="chkShowMarkers">
 | 
			
		||||
                    <strong v-t="'actions.show_markers'" />
 | 
			
		||||
| 
						 | 
				
			
			@ -732,6 +385,17 @@
 | 
			
		|||
                        @change="onChange($event)"
 | 
			
		||||
                    />
 | 
			
		||||
                </label>
 | 
			
		||||
                <label class="pref" for="txtMinSegmentLength" style="border-bottom: var(--efy_border)">
 | 
			
		||||
                    <strong v-t="'actions.min_segment_length'" />
 | 
			
		||||
                    <input
 | 
			
		||||
                        id="txtMinSegmentLength"
 | 
			
		||||
                        v-model="minSegmentLength"
 | 
			
		||||
                        class="input w-24"
 | 
			
		||||
                        type="text"
 | 
			
		||||
                        @change="onChange($event)"
 | 
			
		||||
                    />
 | 
			
		||||
                </label>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -762,21 +426,6 @@
 | 
			
		|||
            </tr>
 | 
			
		||||
        </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
    <!--master-->
 | 
			
		||||
    <br />
 | 
			
		||||
    <p v-t="'info.preferences_note'" />
 | 
			
		||||
    <br />
 | 
			
		||||
    <button v-t="'actions.reset_preferences'" class="btn" @click="showConfirmResetPrefsDialog = true" />
 | 
			
		||||
    <button v-t="'actions.backup_preferences'" class="btn mx-4" @click="backupPreferences()" />
 | 
			
		||||
    <label v-t="'actions.restore_preferences'" for="fileSelector" class="btn" @click="restorePreferences()" />
 | 
			
		||||
    <input id="fileSelector" ref="fileSelector" class="hidden" type="file" @change="restorePreferences()" />
 | 
			
		||||
    <ConfirmModal
 | 
			
		||||
        v-if="showConfirmResetPrefsDialog"
 | 
			
		||||
        :message="$t('actions.confirm_reset_preferences')"
 | 
			
		||||
        @close="showConfirmResetPrefsDialog = false"
 | 
			
		||||
        @confirm="resetPreferences()"
 | 
			
		||||
    />
 | 
			
		||||
    <!--masterend-->
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
| 
						 | 
				
			
			@ -1082,11 +731,37 @@ export default {
 | 
			
		|||
<style>
 | 
			
		||||
.pref {
 | 
			
		||||
    @apply flex justify-between items-center;
 | 
			
		||||
    padding: 10rem;
 | 
			
		||||
    border-top: var(--efy_border);
 | 
			
		||||
    gap: 10rem;
 | 
			
		||||
}
 | 
			
		||||
.pref:nth-child(odd) {
 | 
			
		||||
    @apply bg-gray-200;
 | 
			
		||||
/*.pref:nth-child(odd) {
 | 
			
		||||
    background: var(--efy_bg1);
 | 
			
		||||
}*/
 | 
			
		||||
.pref :is(input, select, button, [role="button"]) {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
.dark .pref:nth-child(odd) {
 | 
			
		||||
    @apply bg-dark-800;
 | 
			
		||||
.pref strong {
 | 
			
		||||
    line-height: 1;
 | 
			
		||||
}
 | 
			
		||||
.pref :is([type="number"], [type="text"], select) {
 | 
			
		||||
    min-width: 60rem;
 | 
			
		||||
    max-width: 250rem;
 | 
			
		||||
}
 | 
			
		||||
.pp-pref-cards {
 | 
			
		||||
    margin-top: 15rem;
 | 
			
		||||
}
 | 
			
		||||
[efy_card*="grid"] {
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    gap: 0;
 | 
			
		||||
}
 | 
			
		||||
[efy_card*="grid"]:active {
 | 
			
		||||
    transform: scale(1) !important;
 | 
			
		||||
}
 | 
			
		||||
[efy_card*="grid"] h5 {
 | 
			
		||||
    padding: 5rem 10rem;
 | 
			
		||||
}
 | 
			
		||||
tbody:nth-child(odd) {
 | 
			
		||||
    background: var(--efy_bg1) !important;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,13 +1,20 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <h1 class="my-2 text-center" v-text="$route.query.search_query" />
 | 
			
		||||
 | 
			
		||||
    <label for="ddlSearchFilters" class="mr-2">
 | 
			
		||||
        <strong v-text="`${$t('actions.filter')}:`" />
 | 
			
		||||
    </label>
 | 
			
		||||
    <select id="ddlSearchFilters" v-model="selectedFilter" default="all" class="select w-auto" @change="updateFilter()">
 | 
			
		||||
    <hr />
 | 
			
		||||
    <div class="flex flex-wrap place-content-between items-center">
 | 
			
		||||
        <h5 class="ml-[5rem]" v-text="$route.query.search_query" />
 | 
			
		||||
        <div class="flex items-center" style="gap: var(--efy_gap0)">
 | 
			
		||||
            <label v-text="`${$t('actions.filter')}:`" for="ddlSearchFilters" />
 | 
			
		||||
            <select
 | 
			
		||||
                id="ddlSearchFilters"
 | 
			
		||||
                v-model="selectedFilter"
 | 
			
		||||
                default="all"
 | 
			
		||||
                class="w-auto; m-0"
 | 
			
		||||
                @change="updateFilter()"
 | 
			
		||||
            >
 | 
			
		||||
                <option v-for="filter in availableFilters" :key="filter" v-t="`search.${filter}`" :value="filter" />
 | 
			
		||||
            </select>
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr />
 | 
			
		||||
 | 
			
		||||
    <div v-if="results && results.corrected">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,6 +90,6 @@ export default {
 | 
			
		|||
    background: var(--efy_text2);
 | 
			
		||||
    box-shadow: 0 0 20rem var(--efy_text_trans);
 | 
			
		||||
    padding: var(--efy_gap);
 | 
			
		||||
    margin: calc(-12rem + var(--efy_gap)) 0 var(--efy_gap) 0;
 | 
			
		||||
    margin: calc(40rem + var(--efy_gap)) 0 var(--efy_gap) 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <label v-t="'actions.sort_by'" for="ddlSortBy" class="mr-2" />
 | 
			
		||||
    <select id="ddlSortBy" v-model="selectedSort" class="select w-auto m-0">
 | 
			
		||||
    <label v-t="'actions.sort_by'" for="ddlSortBy" class="m-0" />
 | 
			
		||||
    <select id="ddlSortBy" v-model="selectedSort" class="w-auto m-0">
 | 
			
		||||
        <option v-for="(value, key) in options" :key="key" v-t="`actions.${key}`" :value="value" />
 | 
			
		||||
    </select>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,11 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <hr />
 | 
			
		||||
    <!-- import / export section -->
 | 
			
		||||
    <div class="w-full flex justify-between">
 | 
			
		||||
        <div class="flex gap-2">
 | 
			
		||||
    <div class="flex justify-between flex-wrap m0c">
 | 
			
		||||
        <div efy_card class="w-auto!" style="padding: var(--efy_padding)">
 | 
			
		||||
            <i18n-t keypath="titles.subscriptions" efy_card />{{ ": " + subscriptions.length }}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="m0c flex flex-wrap">
 | 
			
		||||
            <router-link v-t="'actions.import_from_json_csv'" to="/import" role="button" />
 | 
			
		||||
            <button v-t="'actions.export_to_json'" @click="exportHandler" />
 | 
			
		||||
            <input
 | 
			
		||||
| 
						 | 
				
			
			@ -16,26 +20,28 @@
 | 
			
		|||
                for="fileSelector"
 | 
			
		||||
                role="button"
 | 
			
		||||
                v-text="`${$t('actions.import_from_json')} (${$t('titles.channel_groups')})`"
 | 
			
		||||
                class="font-bold"
 | 
			
		||||
            />
 | 
			
		||||
            <button
 | 
			
		||||
                @click="exportGroupsHandler"
 | 
			
		||||
                v-text="`${$t('actions.export_to_json')} (${$t('titles.channel_groups')})`"
 | 
			
		||||
            />
 | 
			
		||||
        </div>
 | 
			
		||||
        <i18n-t keypath="subscriptions.subscribed_channels_count">{{ subscriptions.length }}</i18n-t>
 | 
			
		||||
    </div>
 | 
			
		||||
    <hr />
 | 
			
		||||
    <div class="w-full flex flex-wrap">
 | 
			
		||||
    <div class="m0c w-full flex flex-wrap">
 | 
			
		||||
        <button
 | 
			
		||||
            v-for="group in channelGroups"
 | 
			
		||||
            :key="group.groupName"
 | 
			
		||||
            class="mx-1 w-max"
 | 
			
		||||
            class="flex gap-[10rem] items-center"
 | 
			
		||||
            :class="{ selected: selectedGroup === group }"
 | 
			
		||||
            @click="selectGroup(group)"
 | 
			
		||||
        >
 | 
			
		||||
            <span v-text="group.groupName !== '' ? group.groupName : $t('video.all')" />
 | 
			
		||||
            <div v-if="group.groupName != '' && selectedGroup == group">
 | 
			
		||||
            <div v-if="group.groupName != '' && selectedGroup == group" class="flex flex-wrap gap-[10rem] items-center">
 | 
			
		||||
                <div>|</div>
 | 
			
		||||
                <font-awesome-icon class="mx-2" icon="edit" @click="showEditGroupModal = true" />
 | 
			
		||||
                <div>|</div>
 | 
			
		||||
                <font-awesome-icon class="mx-2" icon="circle-minus" @click="deleteGroup(group)" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </button>
 | 
			
		||||
| 
						 | 
				
			
			@ -43,7 +49,6 @@
 | 
			
		|||
            <font-awesome-icon icon="circle-plus" @click="showCreateGroupModal = true" />
 | 
			
		||||
        </button>
 | 
			
		||||
    </div>
 | 
			
		||||
    <br />
 | 
			
		||||
    <hr />
 | 
			
		||||
    <!-- Subscriptions card list -->
 | 
			
		||||
    <div class="pp-subs-cards">
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +66,6 @@
 | 
			
		|||
            />
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <br />
 | 
			
		||||
 | 
			
		||||
    <ModalComponent v-if="showCreateGroupModal" @close="showCreateGroupModal = !showCreateGroupModal">
 | 
			
		||||
        <h2 v-t="'actions.create_group'" />
 | 
			
		||||
| 
						 | 
				
			
			@ -101,6 +105,9 @@
 | 
			
		|||
}
 | 
			
		||||
.pp-subs-card :is(a, span) {
 | 
			
		||||
    -webkit-text-fill-color: var(--efy_text) !important;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
}
 | 
			
		||||
.pp-subs-card button {
 | 
			
		||||
    margin-bottom: 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +116,12 @@
 | 
			
		|||
.selected {
 | 
			
		||||
    border: 0.1rem outset red;
 | 
			
		||||
}
 | 
			
		||||
.m0c {
 | 
			
		||||
    gap: var(--efy_gap0);
 | 
			
		||||
}
 | 
			
		||||
.m0c :is(button, [role="button"]) {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <div class="toast">
 | 
			
		||||
        <slot />
 | 
			
		||||
        <button v-t="'actions.dismiss'" @click="dismiss" />
 | 
			
		||||
        <button v-t="'actions.dismiss'" @click="dismiss" class="m-0 mt-[10rem]" />
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,12 +18,11 @@ export default {
 | 
			
		|||
 | 
			
		||||
<style>
 | 
			
		||||
.toast {
 | 
			
		||||
    @apply bg-white/80 text-black flex flex-col justify-center fixed top-12 right-12 p-4 min-w-max shadow rounded duration-200 z-9999;
 | 
			
		||||
}
 | 
			
		||||
.dark .toast {
 | 
			
		||||
    @apply bg-dark-900/80 text-white;
 | 
			
		||||
}
 | 
			
		||||
.toast button {
 | 
			
		||||
    @apply underline;
 | 
			
		||||
    @apply flex flex-col justify-center fixed top-[15rem] right-[15rem] min-w-max z-9999;
 | 
			
		||||
    background: var(--efy_text2);
 | 
			
		||||
    color: var(--efy_text);
 | 
			
		||||
    padding: 15rem;
 | 
			
		||||
    border-radius: var(--efy_radius);
 | 
			
		||||
    border: var(--efy_border);
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <LoadingIndicatorPage :show-content="videos.length != 0" class="video-grid">
 | 
			
		||||
    <LoadingIndicatorPage :show-content="videos.length != 0" class="video-grid mt-[15rem]">
 | 
			
		||||
        <VideoItem v-for="video in videos" :key="video.url" :item="video" height="118" width="210" />
 | 
			
		||||
    </LoadingIndicatorPage>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,8 @@
 | 
			
		|||
<template>
 | 
			
		||||
    <div v-if="showVideo" class="efy_trans_filter efy_shadow_trans">
 | 
			
		||||
    <div v-if="showVideo" class="video-card efy_trans_filter efy_shadow_trans">
 | 
			
		||||
        <!-- EFY-->
 | 
			
		||||
        <router-link
 | 
			
		||||
            class="video_item_link inline-block w-full focus:underline hover:underline"
 | 
			
		||||
            class="video_item_link"
 | 
			
		||||
            :to="{
 | 
			
		||||
                path: '/watch',
 | 
			
		||||
                query: {
 | 
			
		||||
| 
						 | 
				
			
			@ -11,15 +12,43 @@
 | 
			
		|||
                },
 | 
			
		||||
            }"
 | 
			
		||||
        >
 | 
			
		||||
            <!-- EFY
 | 
			
		||||
            <img
 | 
			
		||||
                :src="thumbnail"
 | 
			
		||||
                :alt="title"
 | 
			
		||||
                :class="{ 'shorts-img': item.isShort }"
 | 
			
		||||
                class="thumbnail"
 | 
			
		||||
                loading="lazy"
 | 
			
		||||
            />
 | 
			
		||||
            <!-- progress bar -->
 | 
			
		||||
            <div class="relative h-1 w-full">
 | 
			
		||||
                <div
 | 
			
		||||
                    v-if="item.watched && item.duration > 0"
 | 
			
		||||
                    class="absolute bottom-0 left-0 h-1 bg-red-600"
 | 
			
		||||
                    :style="{ width: `clamp(0%, ${(item.currentTime / item.duration) * 100}%, 100%` }"
 | 
			
		||||
                />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="flex items-center h-[44rem] overflow-hidden">
 | 
			
		||||
                <p v-text="title" class="pp-video-card-title" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </router-link>
 | 
			
		||||
 | 
			
		||||
        <div class="pp-video-card-buttons">
 | 
			
		||||
            <button v-if="item.duration > 0" v-text="timeFormat(item.duration)" tabindex="-1" />
 | 
			
		||||
            <button v-if="item.views >= 0" tabindex="-1">
 | 
			
		||||
                <font-awesome-icon icon="eye" />
 | 
			
		||||
                <span class="pl-0.5" v-text="`${numberFormat(item.views)}`" />
 | 
			
		||||
            <button
 | 
			
		||||
                v-if="item.duration > 0"
 | 
			
		||||
                v-text="timeFormat(item.duration)"
 | 
			
		||||
                class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
 | 
			
		||||
                tabindex="-1"
 | 
			
		||||
            />
 | 
			
		||||
            <button
 | 
			
		||||
                v-if="item.views >= 0"
 | 
			
		||||
                class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
 | 
			
		||||
                tabindex="-1"
 | 
			
		||||
            >
 | 
			
		||||
                <font-awesome-icon icon="eye" style="margin-right: 5rem" />
 | 
			
		||||
                <span v-text="`${numberFormat(item.views)}`" />
 | 
			
		||||
            </button>
 | 
			
		||||
            <router-link
 | 
			
		||||
                class="btn"
 | 
			
		||||
                class="btn efy_shadow_trans efy_shadow_button_off efy_button_text_off"
 | 
			
		||||
                :to="{
 | 
			
		||||
                    path: '/watch',
 | 
			
		||||
                    query: {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,137 +63,11 @@
 | 
			
		|||
            >
 | 
			
		||||
                <font-awesome-icon icon="headphones" />
 | 
			
		||||
            </router-link>
 | 
			
		||||
            <button v-if="authenticated" :title="$t('actions.add_to_playlist')" @click="showModal = !showModal">
 | 
			
		||||
                <font-awesome-icon icon="circle-plus" />
 | 
			
		||||
            </button>
 | 
			
		||||
            <button
 | 
			
		||||
                v-if="admin"
 | 
			
		||||
                :title="$t('actions.remove_from_playlist')"
 | 
			
		||||
                ref="removeButton"
 | 
			
		||||
                @click="removeVideo(item.url.substr(-11))"
 | 
			
		||||
                :title="$t('actions.add_to_playlist')"
 | 
			
		||||
                @click="showModal = !showModal"
 | 
			
		||||
                class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
 | 
			
		||||
            >
 | 
			
		||||
                <font-awesome-icon icon="circle-minus" />
 | 
			
		||||
            </button>
 | 
			
		||||
            <button v-if="item.uploadedDate" class="pl-0.5" v-text="item.uploadedDate" tabindex="-1" />
 | 
			
		||||
            <button class="pp-color" v-if="item.isShort" v-t="'video.shorts'" tabindex="-1" />
 | 
			
		||||
            <button v-else-if="item.duration < 0" v-t="'video.live'" class="pp-color" tabindex="-1" />
 | 
			
		||||
            <button v-if="item.watched" v-t="'video.watched'" class="pp-color" tabindex="-1" />
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <router-link
 | 
			
		||||
            :to="item.uploaderUrl"
 | 
			
		||||
            class="pp-video-card-channel"
 | 
			
		||||
            v-if="item.uploaderUrl && item.uploaderName && !hideChannel"
 | 
			
		||||
        >
 | 
			
		||||
            <img
 | 
			
		||||
                v-if="item.uploaderAvatar"
 | 
			
		||||
                :src="item.uploaderAvatar"
 | 
			
		||||
                loading="lazy"
 | 
			
		||||
                :alt="item.uploaderName"
 | 
			
		||||
                class="mt-0.5 w-36rem h-36rem"
 | 
			
		||||
                width="36"
 | 
			
		||||
                height="36"
 | 
			
		||||
            />
 | 
			
		||||
 | 
			
		||||
            <div class="pp-text" title="item.uploaderName">
 | 
			
		||||
                <span v-text="item.uploaderName" />
 | 
			
		||||
                <font-awesome-icon class="ml-1.5" v-if="item.uploaderVerified" icon="check" />-->
 | 
			
		||||
 | 
			
		||||
            <div class="w-full">
 | 
			
		||||
                <img
 | 
			
		||||
                    class="w-full"
 | 
			
		||||
                    :src="thumbnail"
 | 
			
		||||
                    :alt="title"
 | 
			
		||||
                    :class="{ 'shorts-img': item.isShort, 'opacity-75': item.watched }"
 | 
			
		||||
                    loading="lazy"
 | 
			
		||||
                />
 | 
			
		||||
                <!-- progress bar -->
 | 
			
		||||
                <div class="relative h-1 w-full">
 | 
			
		||||
                    <div
 | 
			
		||||
                        v-if="item.watched && item.duration > 0"
 | 
			
		||||
                        class="absolute bottom-0 left-0 h-1 bg-red-600"
 | 
			
		||||
                        :style="{ width: `clamp(0%, ${(item.currentTime / item.duration) * 100}%, 100%` }"
 | 
			
		||||
                    />
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="relative text-sm">
 | 
			
		||||
                <span
 | 
			
		||||
                    v-if="item.duration > 0"
 | 
			
		||||
                    class="thumbnail-overlay thumbnail-right"
 | 
			
		||||
                    v-text="timeFormat(item.duration)"
 | 
			
		||||
                />
 | 
			
		||||
                <!-- shorts thumbnail -->
 | 
			
		||||
                <span v-if="item.isShort" v-t="'video.shorts'" class="thumbnail-overlay thumbnail-left" />
 | 
			
		||||
                <span
 | 
			
		||||
                    v-else-if="item.duration >= 0"
 | 
			
		||||
                    class="thumbnail-overlay thumbnail-right"
 | 
			
		||||
                    v-text="timeFormat(item.duration)"
 | 
			
		||||
                />
 | 
			
		||||
                <i18n-t v-else keypath="video.live" class="thumbnail-overlay thumbnail-right !bg-red-600" tag="div">
 | 
			
		||||
                    <font-awesome-icon class="w-3" :icon="['fas', 'broadcast-tower']" />
 | 
			
		||||
                </i18n-t>
 | 
			
		||||
                <span v-if="item.watched" v-t="'video.watched'" class="thumbnail-overlay bottom-5px left-5px" />
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <p
 | 
			
		||||
                style="display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical"
 | 
			
		||||
                class="pp-video-card-title my-2 overflow-hidden flex link"
 | 
			
		||||
                :title="title"
 | 
			
		||||
                v-text="title"
 | 
			
		||||
            />
 | 
			
		||||
        </router-link>
 | 
			
		||||
 | 
			
		||||
        <div class="flex">
 | 
			
		||||
            <router-link :to="item.uploaderUrl">
 | 
			
		||||
                <img
 | 
			
		||||
                    v-if="item.uploaderAvatar"
 | 
			
		||||
                    :src="item.uploaderAvatar"
 | 
			
		||||
                    loading="lazy"
 | 
			
		||||
                    class="mr-0.5 mt-0.5 h-32px w-32px rounded-full"
 | 
			
		||||
                    width="68"
 | 
			
		||||
                    height="68"
 | 
			
		||||
                />
 | 
			
		||||
            </router-link>
 | 
			
		||||
 | 
			
		||||
            <div class="flex-1 px-2">
 | 
			
		||||
                <router-link
 | 
			
		||||
                    v-if="item.uploaderUrl && item.uploaderName && !hideChannel"
 | 
			
		||||
                    class="link-secondary block overflow-hidden text-sm"
 | 
			
		||||
                    :to="item.uploaderUrl"
 | 
			
		||||
                    :title="item.uploaderName"
 | 
			
		||||
                >
 | 
			
		||||
                    <span v-text="item.uploaderName" />
 | 
			
		||||
                    <font-awesome-icon v-if="item.uploaderVerified" class="ml-1.5" icon="check" />
 | 
			
		||||
                </router-link>
 | 
			
		||||
 | 
			
		||||
                <div v-if="item.views >= 0 || item.uploadedDate" class="mt-1 text-xs font-normal text-gray-300">
 | 
			
		||||
                    <span v-if="item.views >= 0">
 | 
			
		||||
                        <font-awesome-icon icon="eye" />
 | 
			
		||||
                        <span class="pl-1" v-text="`${numberFormat(item.views)} •`" />
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <span v-if="item.uploaded > 0" class="pl-0.5" v-text="timeAgo(item.uploaded)" />
 | 
			
		||||
                    <span v-else-if="item.uploadedDate" class="pl-0.5" v-text="item.uploadedDate" />
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="flex items-center gap-2.5">
 | 
			
		||||
                <router-link
 | 
			
		||||
                    :to="{
 | 
			
		||||
                        path: '/watch',
 | 
			
		||||
                        query: {
 | 
			
		||||
                            v: item.url.substr(-11),
 | 
			
		||||
                            ...(playlistId && { list: playlistId }),
 | 
			
		||||
                            ...(index >= 0 && { index: index + 1 }),
 | 
			
		||||
                            listen: '1',
 | 
			
		||||
                        },
 | 
			
		||||
                    }"
 | 
			
		||||
                    :aria-label="'Listen to ' + title"
 | 
			
		||||
                    :title="'Listen to ' + title"
 | 
			
		||||
                >
 | 
			
		||||
                    <font-awesome-icon icon="headphones" />
 | 
			
		||||
                </router-link>
 | 
			
		||||
                <button :title="$t('actions.add_to_playlist')" @click="showModal = !showModal">
 | 
			
		||||
                <font-awesome-icon icon="circle-plus" />
 | 
			
		||||
            </button>
 | 
			
		||||
            <button
 | 
			
		||||
| 
						 | 
				
			
			@ -187,12 +90,37 @@
 | 
			
		|||
                :video-info="item"
 | 
			
		||||
                @close="showModal = !showModal"
 | 
			
		||||
            />
 | 
			
		||||
                <!--Master-->
 | 
			
		||||
            <button
 | 
			
		||||
                v-if="item.uploaded > 0"
 | 
			
		||||
                class="efy_shadow_trans efy_shadow_button_off efy_button_text_off"
 | 
			
		||||
                v-text="timeAgo(item.uploaded)"
 | 
			
		||||
            />
 | 
			
		||||
            <button v-else-if="item.uploadedDate" v-text="item.uploadedDate" tabindex="-1" />
 | 
			
		||||
            <button class="pp-color" v-if="item.isShort" v-t="'video.shorts'" tabindex="-1" />
 | 
			
		||||
            <button v-else-if="item.duration < 0" v-t="'video.live'" class="pp-color" tabindex="-1" />
 | 
			
		||||
            <button v-if="item.watched" v-t="'video.watched'" class="pp-color" tabindex="-1" />
 | 
			
		||||
        </div>
 | 
			
		||||
            <!-- </router-link> -->
 | 
			
		||||
 | 
			
		||||
        <router-link
 | 
			
		||||
            v-if="item.uploaderUrl && item.uploaderName && !hideChannel"
 | 
			
		||||
            :to="item.uploaderUrl"
 | 
			
		||||
            :title="item.uploaderName"
 | 
			
		||||
            class="pp-video-card-channel"
 | 
			
		||||
        >
 | 
			
		||||
            <img
 | 
			
		||||
                v-if="item.uploaderAvatar"
 | 
			
		||||
                :src="item.uploaderAvatar"
 | 
			
		||||
                loading="lazy"
 | 
			
		||||
                class="mt-0.5 w-36rem h-36rem efy_shadow_trans efy_shadow_button_off"
 | 
			
		||||
                width="36"
 | 
			
		||||
                height="36"
 | 
			
		||||
            />
 | 
			
		||||
            <div class="pp-text efy_shadow_trans efy_shadow_button_off">
 | 
			
		||||
                <span v-text="item.uploaderName" />
 | 
			
		||||
                <font-awesome-icon class="ml-1.5" v-if="item.uploaderVerified" icon="check" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </router-link>
 | 
			
		||||
    </div>
 | 
			
		||||
    <PlaylistAddModal v-if="showModal" :video-id="video.url.substr(-11)" @close="showModal = !showModal" />
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,8 +11,17 @@
 | 
			
		|||
            ref="previewContainer"
 | 
			
		||||
            class="absolute bottom-0 z-[2000] mb-[3.5%] hidden flex-col items-center"
 | 
			
		||||
        >
 | 
			
		||||
            <canvas id="preview" ref="preview" class="rounded-sm" />
 | 
			
		||||
            <span class="mt-2 w-min rounded-xl bg-dark-700 px-2 pb-1 pt-1.5 text-sm" v-text="timeFormat(currentTime)" />
 | 
			
		||||
            <canvas id="preview" ref="preview" style="border-radius: var(--efy_radius0)" />
 | 
			
		||||
            <span
 | 
			
		||||
                class="w-min"
 | 
			
		||||
                style="
 | 
			
		||||
                    border-radius: var(--efy_radius0);
 | 
			
		||||
                    background: var(--efy_text2);
 | 
			
		||||
                    color: var(--efy_text);
 | 
			
		||||
                    padding: 3rem 6rem;
 | 
			
		||||
                "
 | 
			
		||||
                v-text="timeFormat(currentTime)"
 | 
			
		||||
            />
 | 
			
		||||
        </span>
 | 
			
		||||
        <button
 | 
			
		||||
            v-if="inSegment"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
        />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <LoadingIndicatorPage :show-content="video && !isEmbed" class="w-full">
 | 
			
		||||
    <LoadingIndicatorPage :show-content="video && !isEmbed" class="w-full mt-[15rem]">
 | 
			
		||||
        <ErrorHandler v-if="video && video.error" :message="video.message" :error="video.error" />
 | 
			
		||||
        <Transition>
 | 
			
		||||
            <ToastComponent v-if="shouldShowToast" @dismissed="dismiss">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,7 @@
 | 
			
		|||
    --efy_gap: 15rem;
 | 
			
		||||
    --efy_sidebar_button: right_middle, off;
 | 
			
		||||
    --efy_body_width: 100%;
 | 
			
		||||
     --efy_body_padding: 15rem calc(15rem + var(--efy_gap));
 | 
			
		||||
     --efy_body_padding: 15rem;
 | 
			
		||||
    --efy_font_family: 'nunito', sans-serif,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;
 | 
			
		||||
    --efy_audio_folder: ./efy/audio;
 | 
			
		||||
    --efy_folder: ./efy;
 | 
			
		||||
| 
						 | 
				
			
			@ -45,8 +45,6 @@
 | 
			
		|||
 | 
			
		||||
/*Video Grid */ .video-grid {display: grid; gap: var(--efy_gap); grid-template-columns: repeat(auto-fill, minmax(240rem, 1fr))}
 | 
			
		||||
 | 
			
		||||
tbody:nth-child(odd) {background: var(--efy_bg1)!important; box-shadow: inset 0 0 0 1.5px var(--efy_bg1)}
 | 
			
		||||
 | 
			
		||||
/*Bellow*/ .pp-watch-bellow-options {margin-top: 15rem}
 | 
			
		||||
.pp-watch-buttons {flex-wrap: wrap; gap: var(--efy_gap0)}
 | 
			
		||||
.pp-watch-buttons .btn {padding: 6rem 15rem; border: 0; color: var(--efy_text2); min-height: var(--efy_ratio_width); max-height: var(--efy_ratio_width); place-self: center; place-content: center}
 | 
			
		||||
| 
						 | 
				
			
			@ -95,13 +93,6 @@ tbody:nth-child(odd) {background: var(--efy_bg1)!important; box-shadow: inset 0
 | 
			
		|||
/*Preferences*/ .pp-pref-cards {display: grid; grid-template-columns: repeat(auto-fit, minmax(300rem, 1fr))}
 | 
			
		||||
table {margin-top: 0}
 | 
			
		||||
 | 
			
		||||
/*Chapters*/ .pp-chapters {margin-left: var(--efy_gap); max-width: 400rem; gap: var(--efy_gap0); border-radius: var(--efy_radius)}
 | 
			
		||||
.pp-chapters .chapter {padding: 10rem; border-radius: var(--efy_radius); border: var(--efy_border)}
 | 
			
		||||
.pp-chapters [title=chapters] {padding: 5rem 10rem; border-radius: var(--efy_radius); border: var(--efy_border)}
 | 
			
		||||
.pp-chapters .chapter .flex {gap: 0 15rem}
 | 
			
		||||
 | 
			
		||||
 .pp-chapters.pp-mobile {margin: 15rem 0 0 0; max-width: 100%}
 | 
			
		||||
 | 
			
		||||
/*Modal*/ .modal {backdrop-filter: blur(5px)}
 | 
			
		||||
.modal-container {background: var(--efy_text2)!important; padding: 15rem!important; box-shadow: 0 0 1px var(--efy_text_trans)}
 | 
			
		||||
.modal-container button + button {margin-left: 10rem}
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +106,7 @@ table {margin-top: 0}
 | 
			
		|||
 | 
			
		||||
/*Other*/ .pp-show-recs, .pp-show-playlist, .pp-show-playlist {display: grid; gap: var(--efy_gap)}
 | 
			
		||||
.pp-show-playlist {margin-bottom: 15rem}
 | 
			
		||||
:is(.video-grid, .pp-show-recs, .pp-show-playlist) div {padding: 15rem; background: var(--efy_bg1); border: var(--efy_border)}
 | 
			
		||||
:is(.video-grid, .pp-show-recs, .pp-show-playlist) div {background: var(--efy_bg1); border: var(--efy_border)}
 | 
			
		||||
:is(.video-grid, .pp-show-recs, .pp-show-playlist) div div {padding: 0; border: none; background: transparent}
 | 
			
		||||
 | 
			
		||||
.video-grid > div {
 | 
			
		||||
| 
						 | 
				
			
			@ -160,6 +151,10 @@ table {margin-top: 0}
 | 
			
		|||
    padding: 4rem 10rem;
 | 
			
		||||
    font-weight: normal;
 | 
			
		||||
}
 | 
			
		||||
.thumbnail[src*="/?host=i.ytimg.com"] {
 | 
			
		||||
    aspect-ratio: 16/9;
 | 
			
		||||
    object-fit: cover;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*Convergence*/
 | 
			
		||||
/*Desktop*/
 | 
			
		||||
| 
						 | 
				
			
			@ -172,7 +167,6 @@ table {margin-top: 0}
 | 
			
		|||
@media (max-width: 767.9px) {
 | 
			
		||||
    .pp-rec-vids {grid-template-columns: 1fr 1fr}
 | 
			
		||||
    .\<md\:hidden {display: none}
 | 
			
		||||
    .md\:hidden {margin-bottom: 16rem}
 | 
			
		||||
}
 | 
			
		||||
@media (max-width: 639px) {
 | 
			
		||||
    .pp-rec-vids {grid-template-columns: 1fr}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue