utils: use getBasePath for image URLs

This commit is contained in:
Justin Edmund 2025-12-01 02:26:08 -08:00
parent 220432b40a
commit 19a2b9e77f
6 changed files with 173 additions and 30 deletions

View file

@ -4,13 +4,17 @@ export {
getCharacterImage,
getWeaponImage,
getSummonImage,
getImageUrl as getImageUrlBase
getImageUrl as getImageUrlBase,
getBasePath
} from '$lib/utils/images'
// Import types for local use and re-export
import type { ResourceType, ImageVariant } from '$lib/utils/images'
export type { ResourceType as ResourceKind, ImageVariant }
// Import the base function for the legacy wrapper
import { getImageUrl as getImageUrlFromUtils } from '$lib/utils/images'
// Legacy compatibility wrapper
interface ImageArgs {
type: 'character' | 'weapon' | 'summon'
@ -21,28 +25,5 @@ interface ImageArgs {
}
export function getImageUrl({ type, id, variant, element, pose }: ImageArgs): string {
// Import the base function to avoid circular dependency
import('$lib/utils/images').then(({ getImageUrl: getImageUrlFromUtils }) => {
return getImageUrlFromUtils(type, id, variant, { pose, element })
})
// Temporary direct implementation for sync compatibility
if (!id) return `/images/placeholders/placeholder-${type}-${variant}.png`
const directory = `${type}-${variant}`
const extension = (
(type === 'character' && variant === 'detail') ||
(type === 'weapon' && variant === 'base') ||
(type === 'summon' && variant === 'detail')
) ? '.png' : '.jpg'
if (type === 'character') {
return `/images/${directory}/${id}_${pose || '01'}${extension}`
}
if (type === 'weapon' && variant === 'grid' && element && element > 0) {
return `/images/${directory}/${id}_${element}${extension}`
}
return `/images/${directory}/${id}${extension}`
return getImageUrlFromUtils(type, id, variant, { pose, element })
}

View file

@ -1,3 +1,5 @@
import { getBasePath } from '$lib/utils/images'
interface ElementData {
en: string
ja: string
@ -41,7 +43,7 @@ export function getElementIcon(element?: number): string {
if (label === '—' || label === 'Null') return ''
// Capitalize first letter for filename
const capitalizedLabel = label.charAt(0).toUpperCase() + label.slice(1)
return `/images/labels/element/Label_Element_${capitalizedLabel}.png`
return `${getBasePath()}/labels/element/Label_Element_${capitalizedLabel}.png`
}
export function getElementOptions() {

View file

@ -2,6 +2,8 @@
* Gender mapping utilities for Granblue Fantasy
*/
import { getBasePath } from '$lib/utils/images'
export const GENDER_LABELS: Record<number, string> = {
0: 'Unknown',
1: 'Male',
@ -18,7 +20,7 @@ export function getGenderIcon(gender?: number | null): string {
const label = getGenderLabel(gender)
if (label === '—' || label === 'Unknown') return ''
// Gender icons may use different naming convention
return `/images/labels/gender/Label_Gender_${label.replace('/', '_')}.png`
return `${getBasePath()}/labels/gender/Label_Gender_${label.replace('/', '_')}.png`
}
export function getGenderOptions() {

View file

@ -1,7 +1,12 @@
/**
* Centralized image utility system for all game assets
*
* Supports both local images (development) and remote AWS S3/CDN images (production)
* Configure via PUBLIC_SIERO_IMG_URL environment variable
*/
import { getImageBaseUrl } from '$lib/api/adapters/config'
export type ResourceType = 'character' | 'weapon' | 'summon'
export type ImageVariant = 'main' | 'grid' | 'square' | 'detail' | 'base' | 'wide'
@ -26,8 +31,18 @@ function getFileExtension(type: ResourceType, variant: ImageVariant): string {
return '.jpg'
}
/**
* Gets the base path for images
* Returns AWS S3/CDN URL if configured, otherwise local /images path
*/
export function getBasePath(): string {
const remoteUrl = getImageBaseUrl()
return remoteUrl || '/images'
}
/**
* Gets the placeholder image for a given type and variant
* Placeholders are always served locally
*/
export function getPlaceholderImage(type: ResourceType, variant: ImageVariant): string {
return `/images/placeholders/placeholder-${type}-${variant}.png`
@ -62,7 +77,7 @@ export function getImageUrl(
const directory = getImageDirectory(type, variant)
const extension = getFileExtension(type, variant)
const basePath = `/images/${directory}`
const basePath = `${getBasePath()}/${directory}`
// Handle character-specific logic
if (type === 'character') {
@ -192,3 +207,142 @@ export function getWeaponGridImage(
}
return getImageUrl('weapon', id, 'grid')
}
// ===== Job-Related Images =====
/**
* Get job skill icon URL
*/
export function getJobSkillIcon(slug: string | undefined): string {
if (!slug) return '/images/job-skills/default.png'
return `${getBasePath()}/job-skills/${slug}.png`
}
/**
* Get accessory square image URL
*/
export function getAccessoryImage(granblueId: string | undefined): string {
if (!granblueId) return '/images/placeholders/placeholder-weapon-grid.png'
return `${getBasePath()}/accessory-square/${granblueId}.jpg`
}
// ===== Modification Images =====
/**
* Get awakening image URL
*/
export function getAwakeningImage(slug: string | undefined, extension: 'png' | 'jpg' = 'jpg'): string {
if (!slug) return ''
return `${getBasePath()}/awakening/${slug}.${extension}`
}
/**
* Get weapon key image URL
*/
export function getWeaponKeyImage(slug: string, element?: number): string {
const basePath = `${getBasePath()}/weapon-keys`
// Check if this key type needs element suffix
if (element && isElementalWeaponKey(slug)) {
return `${basePath}/${slug}-${element}.png`
}
return `${basePath}/${slug}.png`
}
/**
* Check if weapon key slug requires element suffix
*/
function isElementalWeaponKey(slug: string): boolean {
const elementalKeys = [
'elemental-teluma',
'pendulum',
'chain-of-causality',
'ultima'
]
return elementalKeys.some((key) => slug.includes(key))
}
/**
* Get AX skill image URL
*/
export function getAxSkillImage(slug: string | undefined): string {
if (!slug) return ''
return `${getBasePath()}/ax/${slug}.png`
}
/**
* Get mastery image URL
*/
export function getMasteryImage(slug: string | undefined): string {
if (!slug) return ''
return `${getBasePath()}/mastery/${slug}.png`
}
// ===== Label Images =====
/**
* Get element label image URL
*/
export function getElementLabelImage(elementName: string): string {
const capitalizedLabel = elementName.charAt(0).toUpperCase() + elementName.slice(1).toLowerCase()
return `${getBasePath()}/labels/element/Label_Element_${capitalizedLabel}.png`
}
/**
* Get proficiency label image URL
*/
export function getProficiencyLabelImage(proficiencyName: string): string {
const capitalizedLabel =
proficiencyName.charAt(0).toUpperCase() + proficiencyName.slice(1).toLowerCase()
return `${getBasePath()}/labels/proficiency/Label_Weapon_${capitalizedLabel}.png`
}
/**
* Get race label image URL
*/
export function getRaceLabelImage(raceName: string): string {
return `${getBasePath()}/labels/race/Label_Race_${raceName}.png`
}
/**
* Get gender label image URL
*/
export function getGenderLabelImage(genderLabel: string): string {
return `${getBasePath()}/labels/gender/Label_Gender_${genderLabel.replace('/', '_')}.png`
}
// ===== Element Icons =====
/**
* Get element icon image URL (for select dropdowns, etc.)
*/
export function getElementIcon(element: number): string {
const elementNames: Record<number, string> = {
1: 'wind',
2: 'fire',
3: 'water',
4: 'earth',
5: 'dark',
6: 'light'
}
const name = elementNames[element] || 'none'
return `${getBasePath()}/elements/element-${name}.png`
}
// ===== Other Game Images =====
/**
* Get guidebook image URL
*/
export function getGuidebookImage(granblueId: string | number | undefined): string {
if (!granblueId) return '/images/placeholders/placeholder-weapon-grid.png'
return `${getBasePath()}/guidebooks/book_${granblueId}.png`
}
/**
* Get raid image URL
*/
export function getRaidImage(slug: string | undefined): string {
if (!slug) return '/images/placeholders/placeholder-weapon-grid.png'
return `${getBasePath()}/raids/${slug}.png`
}

View file

@ -1,3 +1,5 @@
import { getBasePath } from '$lib/utils/images'
export const PROFICIENCY_LABELS: Record<number, string> = {
0: 'None',
1: 'Sabre',
@ -21,7 +23,7 @@ export function getProficiencyIcon(proficiency: number): string {
if (!label || label === 'None') return ''
// Capitalize first letter for filename
const capitalizedLabel = label.charAt(0).toUpperCase() + label.slice(1)
return `/images/labels/proficiency/Label_Weapon_${capitalizedLabel}.png`
return `${getBasePath()}/labels/proficiency/Label_Weapon_${capitalizedLabel}.png`
}
export function getProficiencyOptions() {

View file

@ -2,6 +2,8 @@
* Race mapping utilities for Granblue Fantasy
*/
import { getBasePath } from '$lib/utils/images'
export const RACE_LABELS: Record<number, string> = {
0: 'Unknown',
1: 'Human',
@ -20,7 +22,7 @@ export function getRaceLabel(race?: number | null): string {
export function getRaceIcon(race?: number | null): string {
const label = getRaceLabel(race)
if (label === '—' || label === 'Unknown') return ''
return `/images/labels/race/Label_Race_${label}.png`
return `${getBasePath()}/labels/race/Label_Race_${label}.png`
}
export function getRaceOptions() {