<template> <div :id="`scene-${release.id}`" :class="{ new: release.isNew }" class="tile" > <Details :release="release" class="details-compact" /> <div class="tile-body"> <span class="poster"> <a :href="`/scene/${release.id}/${release.slug || ''}`" target="_blank" rel="noopener noreferrer" class="link" > <img v-if="release.poster" :src="sfw ? `/img/${release.poster.sfw.thumbnail}` : `/media/${release.poster.thumbnail}`" :style="{ 'background-image': sfw ? `/img/${release.poster.sfw.lazy}` : `/media/${release.poster.lazy}` }" :alt="release.title" class="thumbnail" loading="lazy" > <span v-else-if="release.covers && release.covers.length > 0" class="covers" > <img v-for="cover in release.covers" :key="cover.id" :src="sfw ? `/img/${cover.sfw.thumbnail}` : `/media/${cover.thumbnail}`" :style="{ 'background-image': sfw ? `/img/${cover.sfw.lazy}` : `/media/${cover.lazy}` }" :alt="release.title" class="thumbnail cover" loading="lazy" > </span> <div v-else :title="release.title" class="thumbnail unavailable" ><Icon icon="blocked" />No thumbnail available</div> </a> </span> <div class="info"> <Details :release="release" class="details-wide" /> <a :href="`/scene/${release.id}/${release.slug || ''}`" target="_blank" rel="noopener noreferrer" class="row link" > <h3 v-if="release.title" v-tooltip.bottom="release.title" :title="release.title" class="title" >{{ release.title }}</h3> <h3 v-else-if="release.actors.length > 0" class="title title-composed" >{{ release.actors[0].name }} for {{ release.entity.name }}</h3> <h3 v-else class="title title-empty" >{{ release.entity.name }}</h3> </a> <span class="row"> <ul class="actors nolist" :title="release.actors.map(actor => actor.name).join(', ')" > <li v-for="actor in release.actors" :key="actor.id" class="actor" > <router-link :to="{ name: 'actor', params: { actorId: actor.id, actorSlug: actor.slug } }" class="actor-link" >{{ actor.name }}</router-link> </li> </ul> </span> <div class="labels"> <router-link v-if="release.shootId && release.studio" :to="{ name: 'studio', params: { entitySlug: release.studio.slug } }" :title="release.studio && release.studio.name" class="shoot nolink" >{{ release.shootId }}</router-link> <span v-else-if="release.shootId" :title="release.studio && release.studio.name" class="shoot nolink" >{{ release.shootId }}</span> <ul v-if="release.tags.length > 0" :title="release.tags.map(tag => tag.name).join(', ')" class="tags nolist" > <li v-for="tag in release.tags" :key="`tag-${tag.slug}`" class="tag" > <router-link :to="`/tag/${tag.slug}`" class="tag-link" >{{ tag.name }}</router-link> </li> </ul> </div> </div> </div> </div> </template> <script> import Details from './tile-details.vue'; function sfw() { return this.$store.state.ui.sfw; } export default { components: { Details, }, props: { release: { type: Object, default: null, }, }, computed: { sfw, }, }; </script> <style lang="scss" scoped> @import 'breakpoints'; .tile { background: var(--background); position: relative; display: flex; flex-direction: column; box-sizing: border-box; overflow: hidden; height: 100%; box-shadow: 0 0 3px var(--darken-weak); &.new .poster::after { content: '★'; position: absolute; top: 0; left: 0; padding: .05rem .25rem .1rem .15rem; border-radius: 0 0 .5rem 0; color: var(--text-light); background: var(--primary); font-size: .8rem; font-weight: bold; } } .tile-body { display: flex; flex-direction: column; } .poster { position: relative; } .covers { background: var(--profile); display: flex; .cover { width: 50%; } } .thumbnail { width: 100%; height: 14rem; display: flex; justify-content: center; align-items: center; object-fit: cover; background-position: center; background-size: cover; background-color: var(--shadow-hint); color: var(--shadow); text-shadow: 1px 1px 0 var(--highlight); .icon { display: none; width: 2rem; height: 2rem; fill: var(--shadow-hint); } } .row { display: flex; justify-content: space-between; align-items: center; box-sizing: border-box; padding: 0 .5rem; margin: 0 0 .1rem 0; } .info { display: flex; flex-direction: column; flex-grow: 1; overflow: hidden; } .link { text-decoration: none; } .title { margin: 0; color: var(--text); font-size: 1rem; line-height: 1.5; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; } .title-composed, .title-empty { color: var(--shadow); } .actors { word-wrap: break-word; overflow: hidden; max-height: 1.5rem; line-height: 1.5rem; margin: 0 0 .25rem 0; } .actor:not(:last-of-type)::after { content: ","; margin: 0 .25rem 0 0; } .actor-link { color: var(--link); text-decoration: none; &:hover { color: var(--primary); } } .labels { padding: 0 .5rem 1.5rem .5rem; max-height: .5rem; overflow-y: hidden; font-size: 0; line-height: 2; } .shoot { display: inline; padding: .25rem .5rem; background: var(--primary); color: var(--text-light); font-size: 0.75rem; font-weight: bold; box-shadow: inset 0 0 3px var(--shadow-weak); } .tags { display: inline; word-wrap: break-word; } .tag { margin: 0 0 1rem 0; &:not(:first-child) .tag-link { border-left: none; } } .tag-link { background: var(--background); color: var(--shadow); display: inline-block; padding: .25rem .5rem; border: solid 1px var(--shadow-hint); font-size: .75rem; font-weight: bold; text-decoration: none; line-height: 1; &:hover { color: var(--primary); } } .details-wide { margin: 0 0 .5rem 0; } .details-compact { display: none; } @media(max-width: $breakpoint-kilo) { .tile-body { flex-direction: row; } .poster { margin: 0; } .thumbnail { width: 9rem; height: 100%; font-size: 0; box-shadow: 0 0 3px var(--shadow-weak); .icon { display: block; } } .info { padding: .5rem .25rem 0 .25rem; } .row { margin: 0 0 .15rem 0; } .title, .actor-link { font-size: .9rem; } .details-wide { display: none; } .details-compact { display: flex; } .shoot { display: none; } .tile.new .poster::after { bottom: 0; top: auto; padding: .1rem .25rem .05rem .15rem; border-radius: 0 .5rem 0 0; } } </style>