traxxx/assets/components/releases/media.vue

282 lines
5.9 KiB
Vue
Raw Normal View History

<template>
2020-06-29 23:07:48 +00:00
<div class="media">
<div
v-if="release.trailer || release.teaser"
class="trailer-container"
>
2020-05-21 22:55:11 +00:00
<video
v-if="release.trailer"
:src="`/media/${release.trailer.path}`"
:poster="release.poster && (sfw ? `/img/${release.poster.sfw.thumbnail}` : `/media/${release.poster.thumbnail}`)"
:alt="release.title"
:class="{ sfw: sfw && paused }"
class="item trailer"
2020-05-21 22:55:11 +00:00
controls
@playing="playing = true; paused = false;"
@pause="playing = false; paused = true;"
>Sorry, the tailer cannot be played in your browser</video>
2020-05-21 22:55:11 +00:00
<video
v-else-if="release.teaser && /^video\//.test(release.teaser.mime)"
:src="`/media/${release.teaser.path}`"
:poster="release.poster && (sfw ? `/img/${release.poster.sfw.thumbnail}` : `/media/${release.poster.thumbnail}`)"
:alt="release.title"
:class="{ sfw: sfw && paused }"
class="item trailer"
2020-05-21 22:55:11 +00:00
controls
@playing="playing = true; paused = false;"
@pause="playing = false; paused = true;"
>Sorry, the tailer cannot be played in your browser</video>
2020-05-21 22:55:11 +00:00
<img
v-else-if="release.teaser && /^image\//.test(release.teaser.mime)"
:src="sfw ? `/img/${release.teaser.sfw.thumbnail}` : `/media/${release.teaser.path}`"
:alt="release.title"
class="item trailer"
2020-05-21 22:55:11 +00:00
>
2020-03-01 04:28:08 +00:00
2020-05-21 22:55:11 +00:00
<a
v-if="release.poster"
2020-07-01 03:04:02 +00:00
v-tooltip="'View poster'"
2020-05-21 22:55:11 +00:00
:href="`/media/${release.poster.path}`"
:class="{ playing }"
target="_blank"
rel="noopener noreferrer"
class="poster-link"
><Icon icon="image" /></a>
2020-05-21 22:55:11 +00:00
<span
v-if="sfw && !playing"
class="warning"
>
<Icon icon="warning2" />NSFW
</span>
</div>
2020-05-21 22:55:11 +00:00
<template v-if="release.covers && release.covers.length > 0">
<a
v-for="cover in release.covers"
:key="`cover-${cover.id}`"
:href="`/media/${cover.path}`"
target="_blank"
rel="noopener noreferrer"
>
<img
:src="`/media/${cover.thumbnail}`"
class="item cover"
@load="$parent.$emit('load')"
2020-05-21 22:55:11 +00:00
>
</a>
</template>
<div
2020-05-21 22:55:11 +00:00
v-for="photo in photos"
:key="`media-${photo.id}`"
class="item-container"
2020-05-21 22:55:11 +00:00
>
<a
:href="`/media/${photo.path}`"
:class="{ sfw }"
class="item-link"
target="_blank"
rel="noopener noreferrer"
2020-05-21 22:55:11 +00:00
>
<img
:src="sfw ? `/img/${photo.sfw.thumbnail}` : `/media/${photo.thumbnail}`"
:alt="`Photo ${photo.index + 1}`"
class="item"
@load="$parent.$emit('load')"
>
<span
v-if="sfw"
class="warning"
>
<Icon icon="warning2" />NSFW
</span>
</a>
</div>
2020-05-21 22:55:11 +00:00
</div>
</template>
<script>
function sfw() {
2020-05-21 22:55:11 +00:00
return this.$store.state.ui.sfw;
}
function photos() {
const clipPostersById = (this.release.clips || []).reduce((acc, clip) => ({ ...acc, [clip.poster.id]: clip.poster }), {});
const uniqueClipPosters = Array.from(new Set(this.release.clips.map(clip => clip.poster.id) || [])).map(posterId => clipPostersById[posterId]);
const photosWithClipPosters = (this.release.photos || []).concat(uniqueClipPosters);
2020-05-21 22:55:11 +00:00
if (this.release.trailer || this.release.teaser) {
// poster will be on trailer video
return photosWithClipPosters;
2020-05-21 22:55:11 +00:00
}
2020-05-21 22:55:11 +00:00
if (this.release.poster) {
2020-06-29 23:07:48 +00:00
// no trailer, add poster to photos
2020-09-03 21:30:42 +00:00
return [this.release.poster].concat(photosWithClipPosters);
2020-05-21 22:55:11 +00:00
}
2020-06-29 23:07:48 +00:00
// no poster available
return photosWithClipPosters;
}
export default {
2020-05-21 22:55:11 +00:00
props: {
release: {
type: Object,
default: null,
},
expanded: {
type: Boolean,
default: false,
},
2020-05-21 22:55:11 +00:00
},
data() {
return {
playing: false,
paused: false,
};
},
computed: {
photos,
sfw,
},
};
</script>
<style lang="scss" scoped>
@import 'theme';
2020-06-29 23:07:48 +00:00
.media {
flex-shrink: 0;
white-space: nowrap;
overflow-x: auto;
scrollbar-width: none;
scroll-behavior: smooth;
font-size: 0;
&::-webkit-scrollbar {
display: none;
}
&.expanded {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(32rem, 1fr));
grid-gap: 1rem;
justify-content: center;
margin: 0 0 1rem 0;
}
}
2020-03-01 04:28:08 +00:00
.poster-link {
position: absolute;
top: .5rem;
right: .5rem;
transition: opacity .1s ease;
.icon {
width: 1.5rem;
height: 1.5rem;
fill: var(--lighten-strong);
filter: drop-shadow(0 0 1px var(--darken-weak));
2020-03-01 04:28:08 +00:00
}
&.playing {
opacity: 0;
}
&:hover {
cursor: pointer;
opacity: 1;
.icon {
fill: var(--text-light);
}
}
}
.item-container,
2020-06-29 23:07:48 +00:00
.trailer-container {
max-width: 100%;
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
.warning {
display: none;
width: 100%;
height: 100%;
flex-direction: column;
align-items: center;
justify-content: center;
position: absolute;
background: var(--darken-weak);
color: var(--text-light);
font-size: 1.2rem;
font-weight: bold;
2020-04-02 02:05:55 +00:00
text-shadow: 0 0 3px var(--darken-strong);
pointer-events: none;
animation: alert .5s ease infinite .1s;
.icon {
display: block;
fill: var(--text-light);
width: 3rem;
height: 3rem;
margin: 0 0 .25rem 0;
2020-04-02 02:05:55 +00:00
filter: drop-shadow(0 0 3px var(--darken));
animation: alert .5s ease infinite .1s;
2020-03-01 04:28:08 +00:00
}
}
&:hover .warning {
display: inline-flex;
}
2020-03-01 04:28:08 +00:00
}
.item {
2020-07-09 02:31:27 +00:00
height: 18rem;
max-width: 100%;
box-shadow: 0 0 3px var(--shadow-weak);
}
2020-06-29 23:07:48 +00:00
.trailer-container {
height: 18rem;
width: 32rem;
max-width: 100%;
}
.trailer {
width: 100%;
max-height: 100%;
2020-06-29 23:07:48 +00:00
object-fit: cover;
&.sfw {
filter: blur(2rem);
}
}
@keyframes alert {
0% {
color: var(--text-light);
fill: var(--text-light);
}
50% {
color: var(--alert);
fill: var(--alert);
}
}
2020-06-29 23:07:48 +00:00
@media(max-width: $breakpoint0) {
.media:not(.expanded) .item,
.trailer-container {
height: 56vw; /* 16:9 ratio for full-width video */
}
}
</style>