mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-07-14 15:23:10 -05:00
Show identicons for breadcrumbs to match with user profile avatar
This commit is contained in:
parent
d84b5834ac
commit
3cef92e82f
|
|
@ -42,7 +42,7 @@ function generateColors(hash: number) {
|
|||
};
|
||||
}
|
||||
|
||||
function generateIdenticon(input: string, size = 128, gridSize = 5) {
|
||||
export function generateIdenticon(input: string, size = 128, gridSize = 5) {
|
||||
const cacheKey = `${input}-${size}-${gridSize}`;
|
||||
const cached = identiconCache.get(cacheKey);
|
||||
if (cached) return cached;
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ import {
|
|||
SETTINGS_PAGE,
|
||||
userPage,
|
||||
} from "~/utils/urls";
|
||||
import { Avatar } from "../Avatar";
|
||||
import { Avatar, generateIdenticon } from "../Avatar";
|
||||
import { SendouButton } from "../elements/Button";
|
||||
import { SendouPopover } from "../elements/Popover";
|
||||
import { FuseZone } from "../fuse/Fuse";
|
||||
|
|
@ -601,6 +601,9 @@ function SideNavCollapseButton({
|
|||
}
|
||||
|
||||
function PageIcon({ crumb }: { crumb: Breadcrumb }) {
|
||||
const [isErrored, setIsErrored] = React.useState(false);
|
||||
const isClient = useHydrated();
|
||||
|
||||
if (crumb.type !== "IMAGE") {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -609,15 +612,28 @@ function PageIcon({ crumb }: { crumb: Breadcrumb }) {
|
|||
const isExternal = lastPathSegment.includes(".");
|
||||
const iconClass = clsx(styles.pageIcon, "rounded");
|
||||
|
||||
// an <img> can finish loading (and fail) before React hydrates and attaches onError, so that
|
||||
// error is missed — re-check on mount and fall back manually so SSR'd icons still heal
|
||||
const checkAlreadyErrored = (img: HTMLImageElement | null) => {
|
||||
if (img?.complete && img.naturalWidth === 0) setIsErrored(true);
|
||||
};
|
||||
|
||||
const identiconSrc =
|
||||
isErrored && isClient && crumb.identiconInput
|
||||
? generateIdenticon(crumb.identiconInput, 28, 7)
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div className={styles.pageIconWrapper}>
|
||||
{isExternal ? (
|
||||
<img
|
||||
src={crumb.imgPath}
|
||||
ref={checkAlreadyErrored}
|
||||
src={identiconSrc ?? crumb.imgPath}
|
||||
alt=""
|
||||
className={iconClass}
|
||||
width={28}
|
||||
height={28}
|
||||
onError={() => setIsErrored(true)}
|
||||
/>
|
||||
) : (
|
||||
<Image
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ export const handle: SendouRouteHandle = {
|
|||
href: userPage(data.user),
|
||||
type: "IMAGE",
|
||||
text: data.user.username,
|
||||
identiconInput: String(data.user.discordId),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -290,6 +290,8 @@ export type Breadcrumb =
|
|||
type: "IMAGE";
|
||||
href: string;
|
||||
text?: string;
|
||||
/** Seed for the identicon shown if `imgPath` fails to load. */
|
||||
identiconInput?: string;
|
||||
}
|
||||
| { text: string; type: "TEXT"; href: string };
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user