@@ -11,25 +11,35 @@ import { storage } from '~/utils/browser/browser-storage.utils';
11
11
import { debounce } from '~/utils/debounce.utils' ;
12
12
import { arrayMax , findClosestMatch } from '~/utils/math.utils' ;
13
13
14
+ type ImageStoreMedia = {
15
+ poster ?: string ;
16
+ backdrop ?: string ;
17
+ } ;
18
+
14
19
type ImageStore = {
15
- movie : Record < string , string > ;
16
- show : Record < string , string > ;
20
+ movie : Record < string , ImageStoreMedia > ;
21
+ show : Record < string , ImageStoreMedia > ;
17
22
season : Record < string , string > ;
18
23
episode : Record < string , string > ;
19
24
person : Record < string , string > ;
20
25
} ;
21
26
27
+ type ImageStoreTypes = keyof ImageStore ;
28
+
29
+ export type ImageStoreMedias = ImageStoreMedia | string ;
30
+
22
31
export type ImageQuery = {
23
32
id : number ;
24
33
season ?: number ;
25
34
episode ?: number ;
26
- type : keyof ImageStore ;
35
+ type : ImageStoreTypes ;
27
36
} ;
28
37
29
38
type ImagePayload = {
30
- posters ?: TmdbImage [ ] ;
31
- stills ?: TmdbImage [ ] ;
32
- profiles ?: TmdbImage [ ] ;
39
+ posters ?: TmdbImage [ ] ; // movie, show, season
40
+ backdrops ?: TmdbImage [ ] ; // movie or shows
41
+ stills ?: TmdbImage [ ] ; // episodes
42
+ profiles ?: TmdbImage [ ] ; // profiles
33
43
} ;
34
44
35
45
const EmptyImageStore : ImageStore = {
@@ -47,22 +57,22 @@ export const useImageStore = defineStore('data.image', () => {
47
57
const syncSaveImageStore = debounce (
48
58
( _images = images ) =>
49
59
Promise . all ( [
50
- storage . sync . set ( `data.image-store.movie` , _images . movie ) ,
51
- storage . sync . set ( `data.image-store.show` , _images . show ) ,
52
- storage . sync . set ( `data.image-store.season` , _images . season ) ,
53
- storage . sync . set ( `data.image-store.episode` , _images . episode ) ,
54
- storage . sync . set ( `data.image-store.person` , _images . person ) ,
60
+ storage . local . set ( `data.image-store.movie` , _images . movie ) ,
61
+ storage . local . set ( `data.image-store.show` , _images . show ) ,
62
+ storage . local . set ( `data.image-store.season` , _images . season ) ,
63
+ storage . local . set ( `data.image-store.episode` , _images . episode ) ,
64
+ storage . local . set ( `data.image-store.person` , _images . person ) ,
55
65
] ) ,
56
66
1000 ,
57
67
) ;
58
68
59
69
const syncRestoreImageStore = async ( seed ?: Partial < ImageStore > ) => {
60
70
const [ movie , show , season , episode , person ] = await Promise . all ( [
61
- storage . sync . get < Record < string , string > > ( `data.image-store.movie` ) ,
62
- storage . sync . get < Record < string , string > > ( `data.image-store.show` ) ,
63
- storage . sync . get < Record < string , string > > ( `data.image-store.season` ) ,
64
- storage . sync . get < Record < string , string > > ( `data.image-store.episode` ) ,
65
- storage . sync . get < Record < string , string > > ( `data.image-store.person` ) ,
71
+ storage . local . get < Record < string , string > > ( `data.image-store.movie` ) ,
72
+ storage . local . get < Record < string , string > > ( `data.image-store.show` ) ,
73
+ storage . local . get < Record < string , string > > ( `data.image-store.season` ) ,
74
+ storage . local . get < Record < string , string > > ( `data.image-store.episode` ) ,
75
+ storage . local . get < Record < string , string > > ( `data.image-store.person` ) ,
66
76
] ) ;
67
77
if ( seed ) Object . assign ( images , seed ) ;
68
78
if ( movie ) Object . assign ( images . movie , movie ) ;
@@ -102,7 +112,7 @@ export const useImageStore = defineStore('data.image', () => {
102
112
const fetchImageUrl = async (
103
113
key : string ,
104
114
{ id, season, episode, type } : ImageQuery ,
105
- ) : Promise < { image : string ; key : string ; type : ImageQuery [ 'type' ] } | undefined > => {
115
+ ) : Promise < { image : ImageStoreMedias ; key : string ; type : ImageQuery [ 'type' ] } | undefined > => {
106
116
let payload : ImagePayload ;
107
117
if ( type === 'movie' ) {
108
118
payload = await queueRequest ( key , ( ) => TraktService . posters . movie ( id ) ) ;
@@ -116,22 +126,34 @@ export const useImageStore = defineStore('data.image', () => {
116
126
payload = await queueRequest ( key , ( ) => TraktService . posters . show ( id ) ) ;
117
127
} else throw new Error ( 'Unsupported type or missing parameters for fetchImageUrl' ) ;
118
128
119
- const fetchedImages = payload . posters ?? payload . stills ?? payload . profiles ;
120
- if ( ! fetchedImages ?. length ) {
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
- }
133
- return ;
129
+ if ( ( type === 'episode' && ! payload . stills ?. length ) || ( type === 'season' && ! payload . posters ?. length ) ) {
130
+ const sType = 'show' ;
131
+ const sKey = `${ sType } -${ id } ` ;
132
+ if ( images [ sType ] [ sKey ] ) return { image : images [ sType ] [ sKey ] , key : sKey , type : sType } ;
133
+ return fetchImageUrl ( sKey , { id, type : sType } ) ;
134
134
}
135
+
136
+ if ( [ 'movie' , 'show' ] . includes ( type ) ) {
137
+ if ( ! payload . backdrops ?. length && ! payload . posters ?. length ) return ;
138
+ const image = {
139
+ poster : arrayMax ( payload . posters ?? [ ] , 'vote_average' , i => ! ! i . file_path ) ?. file_path ,
140
+ backdrop : arrayMax ( payload . backdrops ?? [ ] , 'vote_average' , i => ! ! i . file_path ) ?. file_path ,
141
+ } ;
142
+ if ( ! image . poster && ! image . backdrop ) return ;
143
+ images [ type ] [ key ] = image ;
144
+
145
+ syncSaveImageStore ( ) . catch ( err => console . error ( 'Failed to save image store' , err ) ) ;
146
+ return { image, key, type } ;
147
+ }
148
+
149
+ if ( type === 'person' && ! payload . profiles ?. length ) return ;
150
+ if ( type === 'season' && ! payload . posters ?. length ) return ;
151
+ if ( type === 'episode' && ! payload . stills ?. length ) return ;
152
+
153
+ const fetchedImages = payload . profiles ?? payload . posters ?? payload . stills ;
154
+
155
+ if ( ! fetchedImages ?. length ) return ;
156
+
135
157
const image = arrayMax ( fetchedImages , 'vote_average' , i => ! ! i . file_path ) ?. file_path ;
136
158
if ( ! image ) return ;
137
159
images [ type ] [ key ] = image ;
@@ -145,24 +167,34 @@ export const useImageStore = defineStore('data.image', () => {
145
167
return findClosestMatch ( size , imageSizes . value . poster ) ;
146
168
} ;
147
169
148
- const getImageUrl = async ( query : ImageQuery , size : number , response : Ref < string | undefined > = ref ( ) ) => {
170
+ const setResponseValue = (
171
+ { image, baseUrl, type, size } : { image : ImageStoreMedias ; baseUrl : string ; type : ImageQuery [ 'type' ] ; size : number } ,
172
+ response : Ref < ImageStoreMedias | undefined > = ref ( ) ,
173
+ ) => {
174
+ if ( typeof image === 'string' ) response . value = `${ baseUrl } ${ getImageSize ( type , size ) } ${ image } ` ;
175
+ else {
176
+ response . value = {
177
+ poster : image . poster ? `${ baseUrl } ${ getImageSize ( type , size ) } ${ image . poster } ` : undefined ,
178
+ backdrop : image . backdrop ? `${ baseUrl } ${ getImageSize ( type , size ) } ${ image . backdrop } ` : undefined ,
179
+ } ;
180
+ }
181
+ return response ;
182
+ } ;
183
+
184
+ const getImageUrl = async ( query : ImageQuery , size : number , response : Ref < ImageStoreMedias | undefined > = ref ( ) ) => {
149
185
if ( ! tmdbConfig . value ) throw new Error ( 'TmdbConfiguration not initialized' ) ;
150
186
if ( ! tmdbConfig . value ?. images ?. secure_base_url ) throw new Error ( 'TmdbConfiguration missing secure_base_url' ) ;
151
187
152
188
const { key, type } = getKeyAndType ( query ) ;
153
189
154
190
const baseUrl = tmdbConfig . value . images . secure_base_url ;
155
191
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 } ` ;
192
+ const image = images [ type ] [ key ] ;
193
+ if ( image ) return setResponseValue ( { image, baseUrl, type, size } , response ) ;
164
194
165
- return response ;
195
+ const result = await fetchImageUrl ( key , query ) ;
196
+ if ( ! result ?. image ) return response ;
197
+ return setResponseValue ( { image : result . image , baseUrl, type, size } , response ) ;
166
198
} ;
167
199
168
200
return { initImageStore, getImageUrl, imageSizes } ;
0 commit comments