fix(avatar): render onError avatars only in client components
CI / check (push) Successful in 4m33s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 1m51s

AvatarImage is used on server pages via UserAvatarThumbnail but lacked
'use client', so the onError handler on its <img> could not cross the
RSC boundary. /login rendered the error page, hanging the news e2e
journey until the 240s test timeout.

- Mark AvatarImage as a client component like ProfileImage
- Replace inline <img onError> on mod/users server pages with the
  client AvatarImage component
This commit is contained in:
openhands committed 2026-09-15 11:43:47 +02:00
1 parent faa37e7c58
commit ce93b92a81
3 files changed
+10 -15

No files matched your search

+4 -7
View File
@@ -2,11 +2,11 @@ import { eq } from "drizzle-orm";
import { notFound } from "next/navigation";
import { getTranslations } from "next-intl/server";
import Link from "@/components/link";
import { AvatarImage } from "@/components/shared/avatar-image";
import { Badge } from "@/components/ui/badge";
import { requireModPermission } from "@/lib/admin/guard";
import { db, User } from "@/lib/db";
import { formatDate } from "@/lib/format-date";
import { avatarImageOnError, getAvatarUrl } from "@/lib/imager";
import { PERMS } from "@/lib/permissions";
export default async function ModUserDetailPage({
@@ -41,15 +41,12 @@ export default async function ModUserDetailPage({
<div className="space-y-6">
<div className="flex flex-wrap items-start justify-between gap-4">
<div className="flex items-center gap-4">
<img
src={getAvatarUrl(user.look, {
direction: 2,
headDirection: 2,
})}
<AvatarImage
figure={user.look}
options={{ size: "m", direction: 2, headDirection: 2 }}
alt=""
width={64}
height={110}
onError={avatarImageOnError}
className="rounded"
/>
<div>
+4 -8
View File
@@ -2,11 +2,11 @@ import { and, asc, count, desc, eq, like, or, type SQL } from "drizzle-orm";
import { getTranslations } from "next-intl/server";
import { DataTable } from "@/components/admin/data-table";
import Link from "@/components/link";
import { AvatarImage } from "@/components/shared/avatar-image";
import { Badge } from "@/components/ui/badge";
import { requireModPermission } from "@/lib/admin/guard";
import { calcPagination, parseListParams } from "@/lib/admin-helpers";
import { db, User } from "@/lib/db";
import { avatarImageOnError, getAvatarUrl } from "@/lib/imager";
import { PERMS } from "@/lib/permissions";
import { logServerError } from "@/lib/server-log";
import type { DataTableColumn } from "@/types/common";
@@ -29,16 +29,12 @@ const columns: DataTableColumn<ModUserRow>[] = [
sortable: true,
render: (_, row) => (
<div className="flex items-center gap-2.5">
<img
src={getAvatarUrl(row.look, {
size: "m",
direction: 2,
headDirection: 2,
})}
<AvatarImage
figure={row.look}
options={{ size: "m", direction: 2, headDirection: 2 }}
alt=""
width={32}
height={32}
onError={avatarImageOnError}
className="rounded"
/>
<span className="font-medium">{row.username}</span>
+2
View File
@@ -1,3 +1,5 @@
"use client";
import {
type AvatarOptions,
avatarImageOnError,