Skip to content

Commit ed6b6f3

Browse files
committed
fix(panel): fix panel routing and shell loading
1 parent 81ddf7f commit ed6b6f3

File tree

11 files changed

+161
-115
lines changed

11 files changed

+161
-115
lines changed

src/components/AppComponent.vue

+4-8
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,12 @@ import { useAuthSettingsStoreRefs } from '~/stores/settings/auth.store';
1313
const { isAuthenticated } = useAuthSettingsStoreRefs();
1414
const { currentRoute, push, back } = useRouter();
1515
16-
const origin = ref();
1716
const panel = ref(false);
1817
1918
watch(
2019
currentRoute,
2120
(_next, _prev) => {
22-
const isPanel = !!_next.meta?.panel;
23-
panel.value = isPanel;
24-
if (origin.value && isPanel) return;
25-
origin.value = isPanel ? _prev : undefined;
21+
panel.value = !!_next.meta?.panel;
2622
},
2723
{
2824
immediate: true,
@@ -32,9 +28,9 @@ watch(
3228
const asideRef = ref();
3329
3430
const onAfterLeave = () => {
35-
if (!origin.value) return;
36-
push(origin.value);
37-
origin.value = undefined;
31+
const base = currentRoute.value?.meta?.base as string;
32+
if (!base) return;
33+
push({ name: base });
3834
};
3935
4036
const onClose = () => {

src/components/common/list/ListItem.vue

-35
Original file line numberDiff line numberDiff line change
@@ -305,41 +305,6 @@ const onClick = () => emit('onItemClick', { item: item?.value });
305305
border-top: 1px solid transparent;
306306
}
307307
}
308-
309-
.poster {
310-
flex: 0 0 var(--poster-width, 5.3125rem);
311-
justify-content: center;
312-
width: var(--poster-width, 5.3125rem);
313-
height: var(--poster-height, 8rem);
314-
opacity: 1;
315-
will-change: opacity;
316-
317-
&.loading {
318-
opacity: 0;
319-
}
320-
321-
&.transition {
322-
transition: opacity 0.5s var(--n-bezier);
323-
324-
&.loading {
325-
transition: opacity 0.1s;
326-
}
327-
}
328-
329-
&.episode {
330-
flex: 0 0 var(--poster-width, 14.23rem);
331-
width: var(--poster-width, 14.23rem);
332-
}
333-
334-
&.placeholder {
335-
position: absolute;
336-
background-color: #111;
337-
}
338-
339-
&:not(.placeholder) {
340-
z-index: layers.$in-front;
341-
}
342-
}
343308
}
344309
</style>
345310

src/components/common/list/use-list-scroll.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ export const useListScroll = <T extends ListScrollSourceItemWithDate<D>, D exten
142142
if (!_item.type) _item.type = getType(item);
143143
if (!_item.title) _item.title = getTitle(item);
144144
if (!_item.content) _item.content = getContent(item);
145-
if (!_item.posterRef) _item.posterRef = ref<string | undefined>(undefined);
145+
if (!_item.posterRef) _item.posterRef = ref<string>();
146146
if (!_item.getPosterQuery) _item.getPosterQuery = getPosterQuery(item, _item.type);
147147
if (!_item.tags) _item.tags = getTags(item, _item.type);
148148

src/components/common/navbar/NavbarComponent.vue

+7-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ const routes = [
2626
Route.Search,
2727
];
2828
29+
const activeRoute = computed(() => {
30+
const _name = route.name?.toString();
31+
if (!_name) return;
32+
return routes.find(r => r === _name) ?? routes.find(r => _name.startsWith(r));
33+
});
34+
2935
const isHover = ref(false);
3036
const isFocus = ref(false);
3137
@@ -53,7 +59,7 @@ const navElement = ref<HTMLElement>();
5359
@focusout="isFocus = false"
5460
>
5561
<NTabs
56-
:value="route.name?.toString()"
62+
:value="activeRoute"
5763
class="tabs"
5864
type="segment"
5965
justify-content="space-evenly"

src/components/common/poster/PosterComponent.vue

+8-4
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const props = defineProps({
2323
default: false,
2424
},
2525
size: {
26-
type: Number,
26+
type: [Number, String] as PropType<number | 'original'>,
2727
required: false,
2828
default: 300,
2929
},
@@ -37,10 +37,12 @@ const onLoad = () => {
3737
imgLoaded.value = true;
3838
};
3939
40+
const localPoster = ref<string>();
41+
4042
const resolvedPoster = computed(() => {
4143
if (poster?.value) return poster.value;
4244
if (item.value.poster) return item.value.poster;
43-
const image = item.value.posterRef?.value;
45+
const image = (item.value.posterRef ?? localPoster)?.value;
4446
if (!image) return;
4547
if (typeof image === 'string') return image;
4648
if (episode.value && 'backdrop' in image) return image.backdrop;
@@ -57,9 +59,11 @@ const timeout = ref();
5759
const { getImageUrl } = useImageStore();
5860
5961
const getPosters = (_item: PosterItem) => {
62+
if (poster?.value) return;
63+
if (_item.poster) return;
64+
6065
imgLoaded.value = false;
6166
if (_item.posterRef?.value) return;
62-
if (!_item.posterRef) return;
6367
const query = _item.getPosterQuery?.();
6468
if (!query) return;
6569
if (!episode.value && _item.type === 'episode') {
@@ -70,7 +74,7 @@ const getPosters = (_item: PosterItem) => {
7074
if (imgLoaded.value) return;
7175
transition.value = true;
7276
}, 100);
73-
getImageUrl(query, size.value, _item.posterRef);
77+
getImageUrl(query, size.value, _item.posterRef ?? localPoster);
7478
};
7579
7680
watch(item, getPosters, { immediate: true, flush: 'post' });

src/components/views/panel/ShowPanel.vue

+69-14
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
<script setup lang="ts">
22
import { NFlex, NSkeleton } from 'naive-ui';
3-
import { onActivated, onDeactivated, ref, toRefs } from 'vue';
3+
import { computed, onActivated, onDeactivated, ref, toRefs } from 'vue';
44
5+
import { useRoute } from 'vue-router';
6+
7+
import type { PosterItem } from '~/models/poster.model';
58
import type { TraktEpisodeExtended } from '~/models/trakt/trakt-episode.model';
69
import type { TraktShowExtended } from '~/models/trakt/trakt-show.model';
710
11+
import type { ImageQuery } from '~/stores/data/image.store';
12+
13+
import PosterComponent from '~/components/common/poster/PosterComponent.vue';
814
import { type ShowSeasons, useShowStore } from '~/stores/data/show.store';
915
1016
const props = defineProps({
@@ -30,18 +36,56 @@ const episode = ref<TraktEpisodeExtended>();
3036
3137
const { showId, seasonNumber, episodeNumber } = toRefs(props);
3238
39+
const seasonNb = computed(() => {
40+
if (!seasonNumber?.value) return;
41+
const _seasonNumber = Number(seasonNumber.value);
42+
if (Number.isNaN(_seasonNumber)) return;
43+
return _seasonNumber;
44+
});
45+
46+
const episodeNb = computed(() => {
47+
if (!episodeNumber?.value) return;
48+
const _episodeNumber = Number(episodeNumber.value);
49+
if (Number.isNaN(_episodeNumber)) return;
50+
return _episodeNumber;
51+
});
52+
53+
const size = computed(() => window?.innerWidth ?? 800 / 2);
54+
55+
const { query } = useRoute();
56+
const posterItem = computed<PosterItem | undefined>(() => {
57+
const poster = query.poster?.toString();
58+
if (poster) return { poster } satisfies PosterItem;
59+
60+
const tmdb = query.tmdb?.toString();
61+
if (!tmdb) return;
62+
const imageQuery: ImageQuery = {
63+
id: tmdb,
64+
season: seasonNb.value,
65+
episode: episodeNb.value,
66+
type: 'show',
67+
};
68+
if (episodeNb.value) imageQuery.type = 'episode';
69+
else if (seasonNb.value) imageQuery.type = 'season';
70+
71+
return {
72+
posterRef: ref(),
73+
getPosterQuery: () => imageQuery,
74+
};
75+
});
76+
3377
const subscriptions = new Set<() => void>();
3478
3579
onActivated(() => {
3680
if (showId?.value) subscriptions.add(getShowRef(showId.value, show).unsub);
3781
if (showId?.value) subscriptions.add(getShowSeasonsRef(showId.value, seasons).unsub);
38-
if (showId?.value && seasonNumber?.value && episodeNumber?.value) {
82+
if (showId?.value && seasonNb?.value && episodeNb?.value) {
3983
subscriptions.add(
4084
getShowEpisodeRef(
4185
{
4286
id: showId.value,
43-
season: Number(seasonNumber.value),
44-
episode: Number(episodeNumber.value),
87+
season: seasonNb.value,
88+
episode: episodeNb.value,
4589
},
4690
episode,
4791
).unsub,
@@ -59,14 +103,25 @@ onDeactivated(() => {
59103
</script>
60104

61105
<template>
62-
<NFlex justify="center" align="center"> </NFlex>
63-
<div>show {{ showId }}</div>
64-
<div v-if="show">show : {{ show?.title }}</div>
65-
<NSkeleton v-else />
66-
<div>season {{ seasonNumber }}</div>
67-
<div v-if="seasons">season {{ Object.keys(seasons) }}</div>
68-
<NSkeleton v-else />
69-
<div>episode {{ episodeNumber }}</div>
70-
<div v-if="episode">episode {{ episode?.title }}</div>
71-
<NSkeleton v-else />
106+
<NFlex justify="center" align="center" vertical>
107+
<NFlex v-if="posterItem" class="poster-container">
108+
<PosterComponent :item="posterItem" :episode="!!episodeNumber" :size="size" />
109+
</NFlex>
110+
<div>show {{ showId }}</div>
111+
<div v-if="show">show : {{ show?.title }}</div>
112+
<NSkeleton v-else />
113+
<div>season {{ seasonNumber }}</div>
114+
<div v-if="seasons">season {{ Object.keys(seasons) }}</div>
115+
<NSkeleton v-else />
116+
<div>episode {{ episodeNumber }}</div>
117+
<div v-if="episode">episode {{ episode?.title }}</div>
118+
<NSkeleton v-else
119+
/></NFlex>
72120
</template>
121+
122+
<style lang="scss" scoped>
123+
.poster-container {
124+
--poster-width: 50dvw;
125+
--poster-height: calc(var(--poster-width) * (9 / 16));
126+
}
127+
</style>

src/components/views/panel/use-panel-item.ts

+30-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const usePanelItem = () => {
1010
if (!type) return;
1111
const { path } = currentRoute.value;
1212
if (!path) return;
13+
const base = path.split('/')[1];
1314
const id = item?.meta?.ids?.[type]?.trakt;
1415
const showId = item?.meta?.ids?.show?.trakt;
1516
const seasonNumber = item?.meta?.number?.season;
@@ -19,14 +20,40 @@ export const usePanelItem = () => {
1920
case 'movie':
2021
case 'show':
2122
if (!id) return;
22-
return push(`${path}/${type}/${id}`);
23+
return push({
24+
name: `${base}-${type}`,
25+
params: { [`${type}Id`]: id },
26+
query: {
27+
poster: item?.poster,
28+
tmdb: item?.meta?.ids?.[type]?.tmdb,
29+
},
30+
});
2331
case 'season':
2432
if (!showId || !seasonNumber) return;
25-
return push({ path: `${path}/show/${showId}/${type}/${seasonNumber}` });
33+
return push({
34+
name: `${base}-${type}`,
35+
params: {
36+
showId,
37+
seasonNumber,
38+
},
39+
query: {
40+
poster: item?.poster,
41+
tmdb: item?.meta?.ids?.show?.tmdb,
42+
},
43+
});
2644
case 'episode':
2745
if (!showId || !seasonNumber || !episodeNumber) return;
2846
return push({
29-
path: `${path}/show/${showId}/season/${seasonNumber}/${type}/${episodeNumber}`,
47+
name: `${base}-${type}`,
48+
params: {
49+
showId,
50+
seasonNumber,
51+
episodeNumber,
52+
},
53+
query: {
54+
poster: item?.poster,
55+
tmdb: item?.meta?.ids?.show?.tmdb,
56+
},
3057
});
3158
default:
3259
break;

0 commit comments

Comments
 (0)