Skip to content

Commit 0581017

Browse files
committed
feat(poster): make backdrop more generic & localise posters
1 parent 431d410 commit 0581017

File tree

11 files changed

+162
-144
lines changed

11 files changed

+162
-144
lines changed

src/components/common/list/ListItem.vue

+4-12
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const props = defineProps({
3232
type: String,
3333
required: false,
3434
},
35-
episode: {
35+
backdrop: {
3636
type: Boolean,
3737
required: false,
3838
},
@@ -82,16 +82,8 @@ const emit = defineEmits<{
8282
8383
const i18n = useI18n('list', 'item');
8484
85-
const {
86-
item,
87-
noHeader,
88-
nextHasHeader,
89-
poster,
90-
episode,
91-
hideDate,
92-
scrollIntoView,
93-
height,
94-
} = toRefs(props);
85+
const { item, noHeader, nextHasHeader, poster, hideDate, scrollIntoView, height } =
86+
toRefs(props);
9587
9688
const onHover = (_hover: boolean) => {
9789
emit('onHover', { item: item?.value, hover: _hover });
@@ -200,7 +192,7 @@ const onClick = () => emit('onItemClick', { item: item?.value });
200192
<PosterComponent
201193
:item="item as PosterItem"
202194
:poster="poster"
203-
:episode="episode"
195+
:backdrop="backdrop"
204196
/>
205197
<ListItemPanel
206198
:item="item"

src/components/common/list/ListScroll.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const props = defineProps({
4040
type: Object as PropType<VirtualListProps>,
4141
required: false,
4242
},
43-
episode: {
43+
backdrop: {
4444
type: Boolean,
4545
required: false,
4646
},
@@ -174,7 +174,7 @@ const onLoadMore = (payload: { page: number; pageCount: number; pageSize: number
174174
:height="listOptions?.itemSize ?? 145"
175175
:size="items.length"
176176
:hide-date="hideDate"
177-
:episode="episode"
177+
:backdrop="backdrop"
178178
:hover="hoverDate === item.date?.current?.toDateString()"
179179
:scroll-into-view="scrollIntoView?.includes(item.id)"
180180
:show-progress="showProgress"

src/components/common/poster/PosterComponent.vue

+7-7
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const props = defineProps({
1717
type: String,
1818
required: false,
1919
},
20-
episode: {
20+
backdrop: {
2121
type: Boolean,
2222
required: false,
2323
default: false,
@@ -29,7 +29,7 @@ const props = defineProps({
2929
},
3030
});
3131
32-
const { episode, poster, item, size } = toRefs(props);
32+
const { backdrop, poster, item, size } = toRefs(props);
3333
3434
const imgLoaded = ref(true);
3535
@@ -45,7 +45,7 @@ const resolvedPoster = computed(() => {
4545
const image = (item.value.posterRef ?? localPoster)?.value;
4646
if (!image) return;
4747
if (typeof image === 'string') return image;
48-
if (episode.value && 'backdrop' in image) return image.backdrop;
48+
if (backdrop.value && 'backdrop' in image) return image.backdrop;
4949
return image.poster;
5050
});
5151
@@ -66,7 +66,7 @@ const getPosters = (_item: PosterItem) => {
6666
if (_item.posterRef?.value) return;
6767
const query = _item.getPosterQuery?.();
6868
if (!query) return;
69-
if (!episode.value && _item.type === 'episode') {
69+
if (!backdrop.value && _item.type === 'episode') {
7070
query.type = 'show';
7171
delete query.episode;
7272
}
@@ -89,7 +89,7 @@ onBeforeUnmount(() => {
8989
alt="poster-image"
9090
class="poster"
9191
:class="{
92-
episode,
92+
backdrop,
9393
loading: !imgLoaded,
9494
transition,
9595
}"
@@ -104,7 +104,7 @@ onBeforeUnmount(() => {
104104
<NImage
105105
alt="poster-image-fallback"
106106
class="poster placeholder"
107-
:class="{ episode }"
107+
:class="{ backdrop }"
108108
object-fit="contain"
109109
width="100%"
110110
lazy
@@ -137,7 +137,7 @@ onBeforeUnmount(() => {
137137
}
138138
}
139139
140-
&.episode {
140+
&.backdrop {
141141
flex: 0 0 var(--poster-width, 14.23rem);
142142
width: var(--poster-width, 14.23rem);
143143
}

src/components/views/calendar/CalendarComponent.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ const { onItemClick } = usePanelItem();
109109
ref="listRef"
110110
:items="list"
111111
:loading="loading"
112-
episode
112+
backdrop
113113
:scroll-into-view="centerItem?.id ? [centerItem?.id] : []"
114114
@on-item-click="onItemClick"
115115
@on-scroll-into-view="e => onScrollIntoOutOfView(false, e.ref)"
+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<script lang="ts" setup>
2+
import { NFlex, NSkeleton } from 'naive-ui';
3+
import { computed, type PropType, ref, toRefs, Transition } from 'vue';
4+
5+
import type { PosterItem } from '~/models/poster.model';
6+
import type { ImageQuery, ImageStoreTypes } from '~/stores/data/image.store';
7+
8+
import PosterComponent from '~/components/common/poster/PosterComponent.vue';
9+
10+
const props = defineProps({
11+
tmdb: {
12+
type: Number,
13+
required: false,
14+
},
15+
mode: {
16+
type: String as PropType<ImageStoreTypes>,
17+
required: true,
18+
},
19+
seasonNumber: {
20+
type: Number,
21+
required: false,
22+
},
23+
episodeNumber: {
24+
type: Number,
25+
required: false,
26+
},
27+
});
28+
29+
const { tmdb, mode, seasonNumber, episodeNumber } = toRefs(props);
30+
31+
const size = computed(() => window?.innerWidth ?? 800 / 2);
32+
33+
const posterItem = computed<PosterItem | undefined>(() => {
34+
const id = tmdb?.value;
35+
const type = mode?.value;
36+
37+
if (!id || !type) return;
38+
39+
const imageQuery: ImageQuery = {
40+
id,
41+
type,
42+
season: seasonNumber?.value,
43+
episode: episodeNumber?.value,
44+
};
45+
46+
return {
47+
posterRef: ref(),
48+
getPosterQuery: () => imageQuery,
49+
};
50+
});
51+
52+
const key = computed(() => {
53+
if (episodeNumber?.value !== undefined && seasonNumber?.value !== undefined) {
54+
return `episode-${episodeNumber.value}-season-${seasonNumber.value}`;
55+
}
56+
if (seasonNumber?.value !== undefined) return `season-${seasonNumber.value}`;
57+
if (tmdb?.value !== undefined) return `tmdb-${tmdb?.value}`;
58+
return `placeholder`;
59+
});
60+
</script>
61+
62+
<template>
63+
<Transition v-if="posterItem" name="scale" mode="out-in">
64+
<NFlex :key="key" class="poster-container" :class="{ landscape: mode !== 'season' }">
65+
<PosterComponent :item="posterItem" :size="size" backdrop />
66+
</NFlex>
67+
</Transition>
68+
<NSkeleton
69+
v-else
70+
class="poster-container skeleton"
71+
:class="{ landscape: mode !== 'season' }"
72+
/>
73+
</template>
74+
75+
<style lang="scss" scoped>
76+
@use '~/styles/transition' as transition;
77+
@include transition.scale;
78+
79+
.poster-container {
80+
--poster-height: calc(50dvw * (9 / 16));
81+
--poster-width: calc(var(--poster-height) * (2 / 3));
82+
83+
&.landscape {
84+
--poster-width: 50dvw;
85+
--poster-height: calc(var(--poster-width) * (9 / 16));
86+
}
87+
88+
&.skeleton {
89+
width: var(--poster-width);
90+
height: var(--poster-height);
91+
}
92+
93+
position: relative;
94+
margin-bottom: 1rem;
95+
border: 1px solid var(--border-white);
96+
box-shadow: var(--image-box-shadow);
97+
}
98+
</style>

src/components/views/panel/ShowPanel.vue

+8-25
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import type {
99
import type { TraktShowExtended } from '~/models/trakt/trakt-show.model';
1010
1111
import TitleLink from '~/components/common/buttons/TitleLink.vue';
12+
import PanelPoster from '~/components/views/panel/PanelPoster.vue';
1213
import ShowPanelDetails from '~/components/views/panel/ShowPanelDetails.vue';
1314
import ShowPanelOverview from '~/components/views/panel/ShowPanelOverview.vue';
1415
import ShowPanelPicker from '~/components/views/panel/ShowPanelPicker.vue';
15-
import ShowPanelPoster from '~/components/views/panel/ShowPanelPoster.vue';
1616
import { ResolveExternalLinks } from '~/settings/external.links';
1717
import { type ShowSeasons, useShowStore } from '~/stores/data/show.store';
1818
import { useExtensionSettingsStore } from '~/stores/settings/extension.store';
@@ -21,7 +21,7 @@ import { deCapitalise } from '~/utils/string.utils';
2121
const props = defineProps({
2222
showId: {
2323
type: String,
24-
required: false,
24+
required: true,
2525
},
2626
seasonNumber: {
2727
type: String,
@@ -65,7 +65,7 @@ const season = computed(() => {
6565
return seasons.value?.[seasonNb.value];
6666
});
6767
68-
const showTitle = computed(() => {
68+
const title = computed(() => {
6969
if (!show.value?.title) return;
7070
return deCapitalise(show.value.title);
7171
});
@@ -146,13 +146,14 @@ const { openTab } = useExtensionSettingsStore();
146146

147147
<template>
148148
<NFlex justify="center" align="center" vertical>
149-
<TitleLink v-if="showTitle" class="show-title" :href="titleUrl" @on-click="openTab">
150-
{{ showTitle }}
149+
<TitleLink v-if="title" class="show-title" :href="titleUrl" @on-click="openTab">
150+
{{ title }}
151151
</TitleLink>
152152
<NSkeleton v-else class="show-title-skeleton" style="width: 50dvh" round />
153153

154-
<ShowPanelPoster
155-
:show-id="show?.ids.tmdb"
154+
<PanelPoster
155+
:tmdb="show?.ids.tmdb"
156+
:mode="panelType"
156157
:season-number="seasonNb"
157158
:episode-number="episodeNb"
158159
/>
@@ -176,24 +177,6 @@ const { openTab } = useExtensionSettingsStore();
176177
</template>
177178

178179
<style lang="scss" scoped>
179-
@use '~/styles/z-index' as layers;
180-
@use '~/styles/transition' as transition;
181-
@include transition.scale;
182-
183-
.poster-container {
184-
--poster-height: calc(50dvw * (9 / 16));
185-
--poster-width: calc(var(--poster-height) * (2 / 3));
186-
187-
&.landscape {
188-
--poster-width: 50dvw;
189-
--poster-height: calc(var(--poster-width) * (9 / 16));
190-
}
191-
192-
position: relative;
193-
border: 1px solid var(--border-white);
194-
box-shadow: var(--image-box-shadow);
195-
}
196-
197180
.show-title:deep(h2),
198181
.show-title-skeleton {
199182
margin-bottom: 1rem;

src/components/views/panel/ShowPanelPoster.vue

-74
This file was deleted.

src/components/views/progress/ProgressComponent.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const { onItemClick } = usePanelItem();
4444
ref="listRef"
4545
:loading="loading"
4646
:items="progress"
47-
episode
47+
backdrop
4848
hide-date
4949
show-progress
5050
@on-scroll="scrolled = true"

0 commit comments

Comments
 (0)