<template> <div class="banner-container" :style="{ 'background-image': `url(${getPath(release.poster || release.covers?.[0] || release.photos?.[0], 'thumbnail')})` }" > <div class="banner"> <div v-if="release.covers?.length > 0 && !release.trailer" class="covers" > <img v-for="cover in release.covers" :key="`cover-${cover.id}`" :src="getPath(cover, 'thumbnail')" class="cover" > </div> <div v-if="release.trailer || release.teaser" class="trailer" > <Player :video="release.trailer || release.teaser" :poster="poster" class="item" :class="{ playing, ['player-movie']: release.covers?.length > 0 && !release.poster, }" @play="playing = true; paused = false;" @pause="playing = false; paused = true;" /> </div> <div v-else-if="release.poster" class="poster-container" > <div class="poster-link"> <img :src="getPath(release.poster, 'thumbnail')" :style="{ 'background-image': `url(${getPath(release.poster, 'lazy')}` }" :width="release.poster.width" :height="release.poster.height" class="poster" > </div> </div> <div v-if="release.photos.length > 0 || release.caps.length > 0 || release.chapters?.some((chapter) => chapter.poster) || coversInAlbum" class="album" :class="{ single: (release.photos.length + release.caps.length + (release.chapters?.filter((chapter) => chapter.poster).length || 0)) === 1 }" > <div v-for="photo in [...(coversInAlbum ? release.covers : []), ...release.photos, ...release.caps, ...(release.chapters?.map((chapter) => chapter.poster).filter(Boolean) || [])]" :key="`photo-${photo.id}`" class="photo-container" > <div class="photo-link"> <img :src="getPath(photo, 'thumbnail')" :style="{ 'background-image': `url(${getPath(photo, 'lazy')})` }" :width="photo.width" :height="photo.height" class="photo" :class="{ [`album-${photo.type}`]: !!photo.type }" > </div> </div> </div> </div> </div> </template> <script setup> import { ref, computed } from 'vue'; import getPath from '#/src/get-path.js'; import Player from '#/components/video/player.vue'; const props = defineProps({ release: { type: Object, default: null, }, }); const playing = ref(false); const paused = ref(false); const poster = computed(() => { if (props.release.poster) { return getPath(props.release.poster, 'thumbnail'); } if (props.release.covers?.length > 0) { return getPath(props.release.covers[0], 'thumbnail'); } if (props.release.photos?.length > 0) { return getPath(props.release.photos[0], 'thumbnail'); } return null; }); const coversInAlbum = props.release.covers?.length > 0 && props.release.trailer; </script> <style scoped> .banner-container { background-position: center; background-size: cover; border-radius: .5rem .5rem 0 0; margin-top: .5rem; box-shadow: 0 0 3px var(--shadow-weak-30); } .banner { max-height: 21rem; border-radius: .5rem 0 0 0; display: flex; font-size: 0; backdrop-filter: brightness(150%) blur(1rem); overflow: hidden; } .poster-container { flex-shrink: 0; margin-right: .5rem; } .poster-link { height: 100%; width: calc(21/9 * 16rem); } .poster { height: 100%; width: 100%; border-radius: .25rem 0 0 0; } .poster, .photo { object-fit: cover; background-size: cover; background-position: center; box-shadow: 0 0 3px var(--shadow-weak-10); } .covers { display: flex; flex-shrink: 0; } .cover { height: 21rem; flex-grow: 1; } .trailer { max-width: 100%; width: calc(21/9 * 16rem); flex-shrink: 0; aspect-ratio: 16/9; } :deep(.player) { width: 100%; height: 100%; &:not(.playing):not(.player-movie) { &[poster], .vjs-tech[poster], .vjs-poster img { object-fit: cover; } } } /* nesting doesn't seem to work? */ :deep(.player.player-movie) { background-color: unset; } .album { height: auto; flex-grow: 1; display: grid; grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr)); gap: .25rem; box-sizing: border-box; padding: .5rem; overflow-y: auto; scrollbar-width: 0; &::-webkit-scrollbar { display: none; } &.single .photo { max-height: calc(100% - 1.5rem); } } .photo-container { display: flex; justify-content: center; align-items: center; flex-grow: 1; } .photo-link { width: 100%; height: 100%; } .photo { width: 100%; height: 100%; border-radius: .25rem; } .album-cover { height: auto; } @media(--compact) { .banner-container { border-radius: 0; margin-top: 0; } } @media(--small-10) { .banner { flex-direction: column; align-items: center; border-radius: 0; max-height: none; } .poster-container { margin: 0; flex-shrink: 1; } .poster-link { width: 100%; } .trailer { flex-shrink: 1; } .poster { border-radius: 0; } .covers { width: 100%; justify-content: center; } .cover { width: 0; height: auto; max-width: min-content; } .album { display: flex; flex-wrap: nowrap; flex-shrink: 0; overflow-x: auto; height: 6rem; padding: .25rem; } .photo-container { flex-grow: 0; flex-shrink: 0; } .album-cover { height: 100%; } } </style>