1
1
import { defineStore , storeToRefs } from 'pinia' ;
2
2
3
- import { computed , reactive , ref } from 'vue' ;
3
+ import { computed , reactive , type Ref , ref } from 'vue' ;
4
4
5
5
import type { TmdbConfiguration } from '~/models/tmdb/tmdb-configuration.model' ;
6
6
@@ -9,7 +9,7 @@ import type { TmdbImage } from '~/models/tmdb/tmdb-image.model';
9
9
import { TraktService } from '~/services/trakt.service' ;
10
10
import { storage } from '~/utils/browser/browser-storage.utils' ;
11
11
import { debounce } from '~/utils/debounce.utils' ;
12
- import { arrayMax } from '~/utils/math.utils' ;
12
+ import { arrayMax , findClosestMatch } from '~/utils/math.utils' ;
13
13
14
14
type ImageStore = {
15
15
movie : Record < string , string > ;
@@ -26,7 +26,11 @@ export type ImageQuery = {
26
26
type : keyof ImageStore ;
27
27
} ;
28
28
29
- type ImagePayload = { posters ?: TmdbImage [ ] ; stills ?: TmdbImage [ ] ; profiles ?: TmdbImage [ ] } ;
29
+ type ImagePayload = {
30
+ posters ?: TmdbImage [ ] ;
31
+ stills ?: TmdbImage [ ] ;
32
+ profiles ?: TmdbImage [ ] ;
33
+ } ;
30
34
31
35
const EmptyImageStore : ImageStore = {
32
36
movie : { } ,
@@ -88,42 +92,77 @@ export const useImageStore = defineStore('data.image', () => {
88
92
return queue [ key ] ;
89
93
} ;
90
94
91
- const fetchImageUrl = async ( key : string , { id, season, episode, type } : ImageQuery ) => {
95
+ const getKeyAndType = ( { id, season, episode, type } : ImageQuery ) : { key : string ; type : ImageQuery [ 'type' ] } => {
96
+ if ( type === 'episode' && season && episode ) return { key : `${ type } -${ id } -${ season } -${ episode } ` , type } ;
97
+ if ( [ 'episode' , 'season' ] . includes ( type ) && season ) return { key : `${ type } -${ id } -${ season } ` , type : 'season' } ;
98
+ if ( [ 'episode' , 'season' , 'show' ] . includes ( type ) ) return { key : `${ type } -${ id } ` , type : 'show' } ;
99
+ return { key : `${ type } -${ id } ` , type } ;
100
+ } ;
101
+
102
+ const fetchImageUrl = async (
103
+ key : string ,
104
+ { id, season, episode, type } : ImageQuery ,
105
+ ) : Promise < { image : string ; key : string ; type : ImageQuery [ 'type' ] } | undefined > => {
92
106
let payload : ImagePayload ;
93
107
if ( type === 'movie' ) {
94
- payload = await queueRequest ( ` ${ type } - ${ id } ` , ( ) => TraktService . posters . movie ( id ) ) ;
108
+ payload = await queueRequest ( key , ( ) => TraktService . posters . movie ( id ) ) ;
95
109
} else if ( type === 'person' ) {
96
- payload = await queueRequest ( ` ${ type } - ${ id } ` , ( ) => TraktService . posters . person ( id ) ) ;
110
+ payload = await queueRequest ( key , ( ) => TraktService . posters . person ( id ) ) ;
97
111
} else if ( type === 'episode' && season && episode ) {
98
- payload = await queueRequest ( ` ${ type } - ${ id } - ${ season } - ${ episode } ` , ( ) => TraktService . posters . episode ( id , season , episode ) ) ;
112
+ payload = await queueRequest ( key , ( ) => TraktService . posters . episode ( id , season , episode ) ) ;
99
113
} else if ( type === 'season' && season ) {
100
- payload = await queueRequest ( ` ${ type } - ${ id } - ${ season } ` , ( ) => TraktService . posters . season ( id , season ) ) ;
101
- } else if ( [ 'show' , 'episode' , 'season' ] . includes ( type ) ) {
102
- payload = await queueRequest ( ` ${ type } - ${ id } ` , ( ) => TraktService . posters . show ( id ) ) ;
114
+ payload = await queueRequest ( key , ( ) => TraktService . posters . season ( id , season ) ) ;
115
+ } else if ( type === 'show' ) {
116
+ payload = await queueRequest ( key , ( ) => TraktService . posters . show ( id ) ) ;
103
117
} else throw new Error ( 'Unsupported type or missing parameters for fetchImageUrl' ) ;
104
118
105
119
const fetchedImages = payload . posters ?? payload . stills ?? payload . profiles ;
106
120
if ( ! fetchedImages ?. length ) {
107
- console . warn ( 'No images found for' , { id, season, episode, type } ) ;
121
+ if ( type === 'episode' ) {
122
+ const eType = 'season' ;
123
+ const eKey = `${ eType } -${ id } -${ season } ` ;
124
+ if ( images [ eType ] [ eKey ] ) return { image : images [ eType ] [ eKey ] , key : eKey , type : eType } ;
125
+ return fetchImageUrl ( eKey , { id, season, type : eType } ) ;
126
+ }
127
+ if ( type === 'season' ) {
128
+ const sType = 'show' ;
129
+ const sKey = `${ sType } -${ id } ` ;
130
+ if ( images [ sType ] [ sKey ] ) return { image : images [ sType ] [ sKey ] , key : sKey , type : sType } ;
131
+ return fetchImageUrl ( sKey , { id, type : sType } ) ;
132
+ }
108
133
return ;
109
134
}
110
135
const image = arrayMax ( fetchedImages , 'vote_average' , i => ! ! i . file_path ) ?. file_path ;
111
136
if ( ! image ) return ;
112
137
images [ type ] [ key ] = image ;
113
- await syncSaveImageStore ( ) ;
138
+ syncSaveImageStore ( ) . catch ( err => console . error ( 'Failed to save image store' , err ) ) ;
139
+ return { image, key, type } ;
114
140
} ;
115
141
116
- const getImageUrl = ( { id, season, episode, type } : ImageQuery , size : string = 'original' ) => {
142
+ const getImageSize = ( type : ImageQuery [ 'type' ] , size : number ) => {
143
+ if ( type === 'person' ) return findClosestMatch ( size , imageSizes . value . poster ) ;
144
+ if ( type === 'episode' ) return findClosestMatch ( size , imageSizes . value . still ) ;
145
+ return findClosestMatch ( size , imageSizes . value . poster ) ;
146
+ } ;
147
+
148
+ const getImageUrl = async ( query : ImageQuery , size : number , response : Ref < string | undefined > = ref ( ) ) => {
117
149
if ( ! tmdbConfig . value ) throw new Error ( 'TmdbConfiguration not initialized' ) ;
118
- const key = [ id , season , episode ] . filter ( Boolean ) . join ( '-' ) ;
119
- const imageRef = computed ( ( ) => images [ type ] [ key ] ) ;
120
- if ( ! imageRef . value ) fetchImageUrl ( key , { id, season, episode, type } ) . catch ( console . error ) ;
121
-
122
- return computed ( ( ) => {
123
- if ( ! imageRef . value ) return ;
124
- if ( ! tmdbConfig . value ?. images ?. secure_base_url ) return ;
125
- return `${ tmdbConfig . value . images . secure_base_url } ${ size } ${ imageRef . value } ` ;
126
- } ) ;
150
+ if ( ! tmdbConfig . value ?. images ?. secure_base_url ) throw new Error ( 'TmdbConfiguration missing secure_base_url' ) ;
151
+
152
+ const { key, type } = getKeyAndType ( query ) ;
153
+
154
+ const baseUrl = tmdbConfig . value . images . secure_base_url ;
155
+
156
+ if ( images [ type ] [ key ] ) {
157
+ response . value = `${ baseUrl } ${ getImageSize ( type , size ) } ${ images [ type ] [ key ] } ` ;
158
+ return response ;
159
+ }
160
+
161
+ const image = await fetchImageUrl ( key , query ) ;
162
+ if ( ! image ) return response ;
163
+ response . value = `${ baseUrl } ${ getImageSize ( image . type , size ) } ${ image . image } ` ;
164
+
165
+ return response ;
127
166
} ;
128
167
129
168
return { initImageStore, getImageUrl, imageSizes } ;
0 commit comments