fix(images) : retry failed CDN images through Cloudflare resizing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { ArrowLeftIcon } from "lucide-react";
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
import { connection } from "next/server";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import { ArrowLeftIcon, ArrowUpRightIcon } from "lucide-react";
|
||||
import { notFound, redirect } from "next/navigation";
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
|
||||
import { SiteFooter } from "@/components/public/site-footer";
|
||||
import { SiteHeader } from "@/components/public/site-header";
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import type { Metadata } from "next";
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import { ExternalLinkIcon } from "lucide-react";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { searchItems } from "@/lib/search";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { ArrowLeftIcon, CheckIcon, SearchIcon } from "lucide-react";
|
||||
import { useMemo, useState, useTransition } from "react";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { searchItems } from "@/lib/search";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { SearchIcon, Trash2Icon } from "lucide-react";
|
||||
import { useMemo, useState, useTransition } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { closestCenter, DndContext, KeyboardSensor, PointerSensor, useSensor, useSensors, type DragEndEvent } from "@dnd-kit/core";
|
||||
import { SortableContext, arrayMove, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { searchItems } from "@/lib/search";
|
||||
|
||||
import dynamic from "next/dynamic";
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import type { MouseEvent } from "react";
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import Image, { getImageProps } from "next/image";
|
||||
import { getImageProps } from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import {
|
||||
closestCenter,
|
||||
DndContext,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { searchItems } from "@/lib/search";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useEffect, useMemo, useRef, useState, useTransition, type ReactNode } from "react";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { CircleHelpIcon } from "lucide-react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import type { ComponentProps, ReactNode } from "react";
|
||||
|
||||
import {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { UserRoundIcon } from "lucide-react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { UserRoundIcon, XIcon } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { ArtifactSelect, CharacterSelect, WeaponSelect } from "@/components/admin/ui/catalog-select";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { ArrowUpRightIcon } from "lucide-react";
|
||||
import type { ReactNode } from "react";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { MousePointerClickIcon } from "lucide-react";
|
||||
import { Children, Fragment, type ReactNode, useState } from "react";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
|
||||
import { GuideExportBranding } from "@/components/public/guide-export-branding";
|
||||
import { ExportText } from "@/components/public/export-language";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
|
||||
import { elementIconFilter } from "@/lib/catalog/element";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
|
||||
export function GuideExportBranding({
|
||||
backgroundUrl,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import { useRef, type PointerEvent } from "react";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { BookOpenIcon, MenuIcon } from "lucide-react";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import { Suspense } from "react";
|
||||
import { PencilIcon } from "lucide-react";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { searchItems } from "@/lib/search";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { SearchIcon, SlidersHorizontalIcon, StarIcon, UsersIcon, XIcon } from "lucide-react";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import localFont from "next/font/local";
|
||||
import Link from "next/link";
|
||||
import { ArrowLeftIcon, ArrowUpRightIcon } from "lucide-react";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import Link from "next/link";
|
||||
import { ArrowUpRightIcon, SearchIcon, XIcon } from "lucide-react";
|
||||
import { Fragment, useMemo, useState, type ReactNode } from "react";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { DownloadIcon } from "lucide-react";
|
||||
import { useState, type ReactNode } from "react";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Image from "next/image";
|
||||
import Image from "@/components/ui/resilient-image";
|
||||
import { CheckIcon, XIcon } from "lucide-react";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
"use client";
|
||||
|
||||
import NextImage, { type ImageProps } from "next/image";
|
||||
import { useState } from "react";
|
||||
|
||||
const CDN_ORIGIN = "https://buzz-cdn.astrxl.dev";
|
||||
|
||||
export default function ResilientImage({ src, unoptimized, onError, ...props }: ImageProps) {
|
||||
const [fallback, setFallback] = useState<{ source: string; url: string } | null>(null);
|
||||
const fallbackUrl = typeof src === "string" && fallback?.source === src ? fallback.url : null;
|
||||
|
||||
return (
|
||||
<NextImage
|
||||
{...props}
|
||||
src={fallbackUrl ?? src}
|
||||
unoptimized={unoptimized || Boolean(fallbackUrl)}
|
||||
onError={(event) => {
|
||||
if (!fallbackUrl && typeof src === "string" && src.startsWith(`${CDN_ORIGIN}/`)) {
|
||||
const source = new URL(src);
|
||||
if (!source.pathname.startsWith("/cdn-cgi/image/")) {
|
||||
const optimized = new URL(event.currentTarget.currentSrc);
|
||||
const width = Number(optimized.searchParams.get("w")) || 1080;
|
||||
const quality = Number(optimized.searchParams.get("q")) || 75;
|
||||
setFallback({
|
||||
source: src,
|
||||
url: `${CDN_ORIGIN}/cdn-cgi/image/width=${width},quality=${quality},format=auto${source.pathname}${source.search}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
onError?.(event);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user