Fixing image url
This commit is contained in:
@@ -189,6 +189,33 @@ const getCategorySilhouette = (category: string) => {
|
|||||||
return silhouettes[normalized] ?? silhouettes.other;
|
return silhouettes[normalized] ?? silhouettes.other;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resolveFirearmImageUrl = (imageUrl: string | null | undefined) => {
|
||||||
|
const trimmed = imageUrl?.trim();
|
||||||
|
|
||||||
|
if (!trimmed) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalized = trimmed.startsWith('//') ? `https:${trimmed}` : trimmed;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = new URL(normalized);
|
||||||
|
|
||||||
|
if (!['http:', 'https:'].includes(parsed.protocol)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsed.hostname === 'commons.wikimedia.org' && parsed.pathname.startsWith('/wiki/File:')) {
|
||||||
|
const fileName = parsed.pathname.replace('/wiki/File:', '');
|
||||||
|
return `https://commons.wikimedia.org/wiki/Special:FilePath/${fileName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsed.toString();
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
@@ -206,6 +233,7 @@ export default function Home() {
|
|||||||
const [newFirearm, setNewFirearm] = useState<FirearmForm>(emptyFirearmForm);
|
const [newFirearm, setNewFirearm] = useState<FirearmForm>(emptyFirearmForm);
|
||||||
const [showNewFirearmForm, setShowNewFirearmForm] = useState(false);
|
const [showNewFirearmForm, setShowNewFirearmForm] = useState(false);
|
||||||
const [selectedFirearmCategory, setSelectedFirearmCategory] = useState(allFirearmCategoriesLabel);
|
const [selectedFirearmCategory, setSelectedFirearmCategory] = useState(allFirearmCategoriesLabel);
|
||||||
|
const [failedFirearmImages, setFailedFirearmImages] = useState<Record<string, boolean>>({});
|
||||||
const [ammoAdjustments, setAmmoAdjustments] = useState<AmmoAdjustments>({});
|
const [ammoAdjustments, setAmmoAdjustments] = useState<AmmoAdjustments>({});
|
||||||
const [ammoPageCaliberIds, setAmmoPageCaliberIds] = useState<string[]>(() => loadStoredAmmoPageSelection());
|
const [ammoPageCaliberIds, setAmmoPageCaliberIds] = useState<string[]>(() => loadStoredAmmoPageSelection());
|
||||||
const [selectedAmmoCaliberId, setSelectedAmmoCaliberId] = useState('');
|
const [selectedAmmoCaliberId, setSelectedAmmoCaliberId] = useState('');
|
||||||
@@ -331,6 +359,7 @@ export default function Home() {
|
|||||||
setFirearmDrafts(
|
setFirearmDrafts(
|
||||||
Object.fromEntries(payload.firearms.map((firearm) => [firearm.id, buildFirearmForm(firearm)])),
|
Object.fromEntries(payload.firearms.map((firearm) => [firearm.id, buildFirearmForm(firearm)])),
|
||||||
);
|
);
|
||||||
|
setFailedFirearmImages({});
|
||||||
setAmmoAdjustments(buildAmmoAdjustments(payload.ammoInventory));
|
setAmmoAdjustments(buildAmmoAdjustments(payload.ammoInventory));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -616,6 +645,18 @@ export default function Home() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleFirearmChange = (id: string, field: keyof FirearmForm, value: string) => {
|
const handleFirearmChange = (id: string, field: keyof FirearmForm, value: string) => {
|
||||||
|
if (field === 'imageUrl') {
|
||||||
|
setFailedFirearmImages((current) => {
|
||||||
|
if (!current[id]) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = { ...current };
|
||||||
|
delete next[id];
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
setFirearmDrafts((current) => ({
|
setFirearmDrafts((current) => ({
|
||||||
...current,
|
...current,
|
||||||
[id]: {
|
[id]: {
|
||||||
@@ -1043,14 +1084,25 @@ export default function Home() {
|
|||||||
) : (
|
) : (
|
||||||
filteredFirearms.map((firearm) => {
|
filteredFirearms.map((firearm) => {
|
||||||
const draft = firearmDrafts[firearm.id] ?? buildFirearmForm(firearm);
|
const draft = firearmDrafts[firearm.id] ?? buildFirearmForm(firearm);
|
||||||
|
const resolvedImageUrl = resolveFirearmImageUrl(draft.imageUrl);
|
||||||
|
const firearmImageSrc = !failedFirearmImages[firearm.id] && resolvedImageUrl
|
||||||
|
? resolvedImageUrl
|
||||||
|
: getCategorySilhouette(draft.category);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article className="firearm-card" key={firearm.id}>
|
<article className="firearm-card" key={firearm.id}>
|
||||||
<div className="firearm-visual">
|
<div className="firearm-visual">
|
||||||
<img
|
<img
|
||||||
className={draft.imageUrl ? 'firearm-photo' : 'firearm-silhouette'}
|
className={!failedFirearmImages[firearm.id] && resolvedImageUrl ? 'firearm-photo' : 'firearm-silhouette'}
|
||||||
alt={`${firearm.manufacturer} ${firearm.model}`}
|
alt={`${firearm.manufacturer} ${firearm.model}`}
|
||||||
src={draft.imageUrl || getCategorySilhouette(draft.category)}
|
loading="lazy"
|
||||||
|
referrerPolicy="no-referrer"
|
||||||
|
onError={() =>
|
||||||
|
setFailedFirearmImages((current) =>
|
||||||
|
current[firearm.id] ? current : { ...current, [firearm.id]: true },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
src={firearmImageSrc}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-grid">
|
<div className="form-grid">
|
||||||
|
|||||||
Reference in New Issue
Block a user