@@ -92,6 +92,16 @@ const getInitials = (username: string) => {
9292 return username . slice ( 0 , 2 ) . toUpperCase ( ) ;
9393} ;
9494
95+ // Resolve a media path to a full URL, stripping /api suffix from baseURL if present
96+ const getMediaUrl = ( path : string ) : string => {
97+ if ( ! path ) return '' ;
98+ if ( path . startsWith ( 'http://' ) || path . startsWith ( 'https://' ) ) return path ;
99+ const base = ( ( api . defaults as any ) ?. baseURL || '' )
100+ . replace ( / \/ a p i \/ ? $ / , '' )
101+ . replace ( / \/ $ / , '' ) ;
102+ return `${ base } ${ path . startsWith ( '/' ) ? '' : '/' } ${ path } ` ;
103+ } ;
104+
95105const PluginDetail = ( ) => {
96106 const { t } = useTranslation ( ) ;
97107 const { id } = useParams ( ) ;
@@ -134,7 +144,9 @@ const PluginDetail = () => {
134144 const res = await api . get ( `/plugins/${ id } ` ) ;
135145 setPlugin ( res . data ) ;
136146 setCurrentDescription ( res . data . description || '' ) ;
137- if ( res . data . screenshots ?. length > 0 ) setMainScreenshot ( res . data . screenshots [ 0 ] ) ;
147+ if ( res . data . screenshots ?. length > 0 ) {
148+ setMainScreenshot ( res . data . screenshots [ 0 ] ) ;
149+ }
138150 } catch ( err ) {
139151 console . error ( 'Fetch error:' , err ) ;
140152 } finally {
@@ -293,6 +305,11 @@ const PluginDetail = () => {
293305 }
294306 } ;
295307
308+ // Derive the GitHub repo label from the source link
309+ const githubLabel = plugin . source_link
310+ ? plugin . source_link . replace ( / ^ h t t p s ? : \/ \/ ( w w w \. ) ? g i t h u b \. c o m \/ / , '' )
311+ : '' ;
312+
296313 return (
297314 < div className = "container" >
298315 < SEO
@@ -349,17 +366,23 @@ const PluginDetail = () => {
349366 { plugin . screenshots ?. length > 0 && (
350367 < section className = "screenshots-premium" >
351368 < div className = "main-screenshot-wrapper" >
352- < img src = { mainScreenshot || plugin . screenshots [ 0 ] } alt = "Plugin Preview" className = "main-screenshot" />
369+ < img
370+ src = { getMediaUrl ( mainScreenshot || plugin . screenshots [ 0 ] ) }
371+ alt = "Plugin Preview"
372+ className = "main-screenshot"
373+ onError = { e => { ( e . target as HTMLImageElement ) . style . display = 'none' ; } }
374+ />
353375 </ div >
354376 { plugin . screenshots . length > 1 && (
355377 < div className = "screenshot-thumbnails" >
356378 { plugin . screenshots . map ( ( s : string , i : number ) => (
357379 < img
358380 key = { i }
359- src = { s }
381+ src = { getMediaUrl ( s ) }
360382 alt = "Thumbnail"
361383 className = { `thumb ${ mainScreenshot === s ? 'active' : '' } ` }
362384 onClick = { ( ) => setMainScreenshot ( s ) }
385+ onError = { e => { ( e . target as HTMLImageElement ) . style . display = 'none' ; } }
363386 />
364387 ) ) }
365388 </ div >
@@ -455,7 +478,8 @@ const PluginDetail = () => {
455478 )
456479 ) : (
457480 < div className = "auth-notice" >
458- { t ( 'reviews.login_to_rate' ) } < Link to = "/login" > { t ( 'login' ) . toLowerCase ( ) } </ Link > . </ div >
481+ { t ( 'reviews.login_to_rate' ) } < Link to = "/login" > { t ( 'login' ) . toLowerCase ( ) } </ Link > .
482+ </ div >
459483 ) }
460484 </ section >
461485 </ div >
@@ -477,9 +501,7 @@ const PluginDetail = () => {
477501 < div >
478502 { plugin . sale_active && plugin . sale_discount_percent > 0 ? (
479503 < div style = { { display : 'flex' , flexDirection : 'column' , gap : '0.2rem' } } >
480- { /* Sale price prominent */ }
481504 < PriceDisplay cents = { Math . round ( plugin . price_cents * ( 1 - plugin . sale_discount_percent / 100 ) ) } />
482- { /* Original price struck through */ }
483505 < div style = { { display : 'flex' , alignItems : 'center' , gap : '0.5rem' } } >
484506 < span style = { { fontSize : '0.85rem' , color : 'var(--text-muted)' , textDecoration : 'line-through' , fontFamily : 'var(--font-mono)' } } >
485507 €{ ( plugin . price_cents / 100 ) . toFixed ( 2 ) }
@@ -508,17 +530,16 @@ const PluginDetail = () => {
508530 </ button >
509531
510532 { plugin . source_link && (
511- < a
512- href = { plugin . source_link }
513- target = "_blank"
514- rel = "noopener noreferrer"
515- className = "btn btn-outline"
516- style = { { display : 'flex' , alignItems : 'center' , justifyContent : 'center' , gap : '8px' , fontSize : '0.85rem' } }
533+ < a
534+ href = { plugin . source_link }
535+ target = "_blank"
536+ rel = "noopener noreferrer"
537+ className = "btn-github-link"
517538 >
518- < svg width = "18 " height = "18 " viewBox = "0 0 24 24" fill = "currentColor" >
539+ < svg width = "14 " height = "14 " viewBox = "0 0 24 24" fill = "currentColor" style = { { flexShrink : 0 } } >
519540 < path d = "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
520541 </ svg >
521- { plugin . source_link . replace ( / ^ h t t p s ? : \/ \/ ( w w w \. ) ? g i t h u b \. c o m \/ / , '' ) }
542+ < span > { githubLabel } </ span >
522543 </ a >
523544 ) }
524545
@@ -527,7 +548,6 @@ const PluginDetail = () => {
527548 < div className = "stat-item" > < strong > { plugin . views . toLocaleString ( ) } </ strong > { t ( 'plugins.views' ) } </ div >
528549 < div className = "stat-item" > { t ( 'plugins.category' ) } : < strong > { plugin . category } </ strong > </ div >
529550
530- { /* ADD THESE TWO */ }
531551 { plugin . version && (
532552 < div className = "stat-item" > { t ( 'plugins.version' ) } : < strong > { plugin . version } </ strong > </ div >
533553 ) }
@@ -585,4 +605,4 @@ const PluginDetail = () => {
585605 ) ;
586606} ;
587607
588- export default PluginDetail ;
608+ export default PluginDetail ;
0 commit comments