import { resolveProjectBase } from '@/themeConfig' import type { User } from '@/models/login' export interface ProductFile { id?: number url?: string | null src?: string full_src?: string } function projectBase(): string { return resolveProjectBase().replace(/\/$/, '') } function storageRelativePath(value: string): string | null { const match = value.match(/(?:^|\/)(storage\/.+)$/i) return match ? match[1].replace(/^\/+/, '') : null } function joinProjectUrl(relative: string): string { const path = relative.replace(/^\//, '') let base = projectBase() if (!base && typeof window !== 'undefined') { base = `${window.location.origin}/server` } if (!base) { return `/server/${path}` } base = base.replace(/\/$/, '') if (path.startsWith('storage/') && !/\/(server|api)(\/|$)/i.test(base)) { base = `${base}/server` } let url = `${base}/${path}` if (typeof window !== 'undefined' && window.location.protocol === 'https:') { url = url.replace(/^http:\/\//i, 'https://') } return url } /** * URL فایل روی API — مسیرهای `storage/` و آدرس‌های localhost/http * را به `node_server` می‌چسباند تا روی اندروید (PWA/TWA) لود شوند. */ export function normalizePublicFileUrl(raw?: string | null): string | null { if (raw == null) return null const trimmed = String(raw).trim() if (!trimmed || trimmed.toLowerCase() === 'null' || trimmed.toLowerCase() === 'undefined') { return null } if (/^(data:|blob:)/i.test(trimmed)) return trimmed const storagePath = storageRelativePath(trimmed) if (storagePath) { return joinProjectUrl(storagePath) } if (/^https?:\/\//i.test(trimmed)) { if (typeof window !== 'undefined' && window.location.protocol === 'https:') { return trimmed.replace(/^http:\/\//i, 'https://') } return trimmed } return joinProjectUrl(trimmed) } export function getFileUrl(file?: ProductFile | null): string | null { if (!file) return null for (const value of [file.full_src, file.url, file.src]) { if (!value) continue const normalized = normalizePublicFileUrl(value) if (normalized) return normalized } return null } /** Resolve profile avatar URL from GET /customer/me payload */ export function getUserAvatarUrl(user?: User | null): string | null { if (!user) return null if (typeof user.avatar_url === 'string' && user.avatar_url) { return normalizePublicFileUrl(user.avatar_url) } if (typeof user.full_src === 'string' && user.full_src) { return normalizePublicFileUrl(user.full_src) } const nested = user.avatar || user.file return getFileUrl(nested as ProductFile | undefined) }