Skip to content

Commit 1535f59

Browse files
committed
fix(poster): auto-resize to portrait if no backdrop found
1 parent 9c570b6 commit 1535f59

File tree

5 files changed

+47
-13
lines changed

5 files changed

+47
-13
lines changed

src/components/common/list/ListItem.vue

+6-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ const props = defineProps({
3636
type: Boolean,
3737
required: false,
3838
},
39+
posterType: {
40+
type: String as PropType<PosterItem['type']>,
41+
required: false,
42+
},
3943
color: {
4044
type: String,
4145
required: false,
@@ -228,6 +232,7 @@ const onClick = () => emit('onItemClick', { item: item?.value });
228232
v-if="!hidePoster"
229233
:item="item as PosterItem"
230234
:poster="poster"
235+
:type="posterType"
231236
:backdrop="backdrop"
232237
/>
233238
<ListItemPanel
@@ -273,7 +278,7 @@ const onClick = () => emit('onItemClick', { item: item?.value });
273278
@include mixin.hover-background(
274279
$from: transparent,
275280
$to: var(--bg-color-20),
276-
$transition: 0.4s var(--n-bezier)
281+
$transition: 0.3s var(--n-bezier)
277282
);
278283
279284
flex: 1 1 auto;

src/components/common/list/ListScroll.vue

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import type { PropType, Ref, Transition } from 'vue';
77
88
import type { StorePagination } from '~/models/pagination.model';
99
10+
import type { PosterItem } from '~/models/poster.model';
11+
1012
import ListEmpty from '~/components/common/list/ListEmpty.vue';
1113
import ListItem from '~/components/common/list/ListItem.vue';
1214
import ListLoadMore from '~/components/common/list/ListLoadMore.vue';
@@ -48,6 +50,10 @@ const props = defineProps({
4850
type: Boolean,
4951
required: false,
5052
},
53+
posterType: {
54+
type: String as PropType<PosterItem['type']>,
55+
required: false,
56+
},
5157
hidePoster: {
5258
type: Boolean,
5359
required: false,
@@ -301,6 +307,7 @@ const listPaddingBottom = computed(() => {
301307
:hide-time="hideTime"
302308
:hide-poster="!showPoster"
303309
:backdrop="showBackdrop"
310+
:poster-type="posterType"
304311
:content-height="contentHeight"
305312
:hover="hoverDate === item.date?.current?.toDateString()"
306313
:scroll-into-view="scrollIntoView?.includes(item.id)"

src/components/common/poster/PosterComponent.vue

+32-11
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ const props = defineProps({
1414
type: Object as PropType<PosterItem>,
1515
required: true,
1616
},
17+
type: {
18+
type: String as PropType<PosterItem['type']>,
19+
required: false,
20+
},
1721
poster: {
1822
type: String,
1923
required: false,
@@ -30,7 +34,7 @@ const props = defineProps({
3034
},
3135
});
3236
33-
const { backdrop, poster, item, size } = toRefs(props);
37+
const { backdrop, poster, item, size, type } = toRefs(props);
3438
3539
// Local poster is used when the item has no poster ref of its own.
3640
const localPoster = ref<ImageStoreMedias>();
@@ -48,20 +52,31 @@ const resolvedPoster = computed(() => {
4852
}
4953
if (!image) return;
5054
if (typeof image === 'string') return image;
51-
if (backdrop.value && 'backdrop' in image) return image.backdrop;
52-
return image.poster;
55+
if (backdrop.value && 'backdrop' in image) return image.backdrop ?? image.poster;
56+
return image.poster ?? image.backdrop;
5357
});
5458
55-
const objectFit = computed(() =>
56-
resolvedPoster.value === PosterPlaceholder ? 'contain' : 'cover',
57-
);
58-
5959
const transition = ref(false);
6060
6161
const imgLoaded = ref(false);
6262
const loading = computed(() => !imgLoaded.value || !resolvedPoster.value);
6363
64+
const imageRef = ref<typeof NImage>();
65+
const dimensions = ref<{ width: number; height: number; ratio: number }>();
66+
const portrait = computed(() => dimensions.value?.ratio && dimensions.value.ratio < 1);
67+
68+
const objectFit = computed(() =>
69+
resolvedPoster.value === PosterPlaceholder ? 'contain' : 'cover',
70+
);
71+
6472
const onLoad = () => {
73+
const { naturalWidth, naturalHeight }: HTMLImageElement =
74+
imageRef.value?.$el?.firstElementChild ?? {};
75+
dimensions.value = {
76+
width: naturalWidth,
77+
height: naturalHeight,
78+
ratio: Math.round((naturalWidth / naturalHeight) * 100) / 100,
79+
};
6580
imgLoaded.value = true;
6681
};
6782
@@ -73,9 +88,10 @@ const getPosters = async (_item: PosterItem) => {
7388
7489
const query = _item.getPosterQuery?.();
7590
if (!query) return;
76-
if (!backdrop.value && _item.type === 'episode') {
77-
query.type = 'show';
78-
delete query.episode;
91+
if (type?.value && type.value !== _item.type) {
92+
query.type = type.value;
93+
if (_item.type === 'episode') delete query.episode;
94+
if (_item.type === 'season') delete query.season;
7995
}
8096
// If the image is not loaded after 100ms, show transition
8197
clearTimeout(timeout.value);
@@ -103,9 +119,11 @@ onBeforeUnmount(() => {
103119

104120
<template>
105121
<NImage
122+
ref="imageRef"
106123
alt="poster-image"
107124
class="poster"
108125
:class="{
126+
portrait,
109127
backdrop,
110128
loading,
111129
transition,
@@ -121,7 +139,10 @@ onBeforeUnmount(() => {
121139
<NImage
122140
alt="poster-image-fallback"
123141
class="poster placeholder"
124-
:class="{ backdrop }"
142+
:class="{
143+
portrait,
144+
backdrop,
145+
}"
125146
object-fit="contain"
126147
width="100%"
127148
lazy

src/components/views/history/HistoryComponent.vue

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ useActiveAndDocumentVisible({
8181
:pagination="pagination"
8282
:page-size="pageSize"
8383
show-collected
84+
show-tag-loader
8485
@on-scroll="scrolled = true"
8586
@on-scroll-top="scrolled = false"
8687
@on-scroll-bottom="onScroll"

src/components/views/panel/PanelPoster.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ const { openTab } = useLinksStore();
115115
cursor: pointer;
116116
}
117117
118-
&.landscape {
118+
&.landscape:not(:has(.poster.portrait)) {
119119
--poster-width: min(var(--half-width), var(--height-70-dvh));
120120
--poster-height: calc(var(--poster-width) * (9 / 16));
121121
}

0 commit comments

Comments
 (0)