2022-12-10 12:14:48 +03:00
|
|
|
import './avatar.css';
|
|
|
|
|
2023-03-13 05:10:21 +03:00
|
|
|
import { useRef } from 'preact/hooks';
|
|
|
|
|
2022-12-10 12:14:48 +03:00
|
|
|
const SIZES = {
|
|
|
|
s: 16,
|
|
|
|
m: 20,
|
|
|
|
l: 24,
|
|
|
|
xl: 32,
|
|
|
|
xxl: 50,
|
2022-12-17 19:38:19 +03:00
|
|
|
xxxl: 64,
|
2022-12-10 12:14:48 +03:00
|
|
|
};
|
|
|
|
|
2023-03-13 09:24:53 +03:00
|
|
|
const alphaCache = {};
|
|
|
|
|
2023-01-21 19:37:46 +03:00
|
|
|
function Avatar({ url, size, alt = '', ...props }) {
|
2022-12-10 12:14:48 +03:00
|
|
|
size = SIZES[size] || size || SIZES.m;
|
2023-03-13 05:10:21 +03:00
|
|
|
const avatarRef = useRef();
|
2022-12-10 12:14:48 +03:00
|
|
|
return (
|
|
|
|
<span
|
2023-03-13 05:10:21 +03:00
|
|
|
ref={avatarRef}
|
2023-03-13 09:24:53 +03:00
|
|
|
class={`avatar ${alphaCache[url] ? 'has-alpha' : ''}`}
|
2022-12-10 12:14:48 +03:00
|
|
|
style={{
|
|
|
|
width: size,
|
|
|
|
height: size,
|
|
|
|
}}
|
2022-12-14 17:46:50 +03:00
|
|
|
title={alt}
|
2023-01-21 19:37:46 +03:00
|
|
|
{...props}
|
2022-12-10 12:14:48 +03:00
|
|
|
>
|
|
|
|
{!!url && (
|
2023-03-13 05:10:21 +03:00
|
|
|
<img
|
|
|
|
src={url}
|
|
|
|
width={size}
|
|
|
|
height={size}
|
|
|
|
alt={alt}
|
|
|
|
loading="lazy"
|
2023-03-13 09:24:53 +03:00
|
|
|
crossOrigin={alphaCache[url] === undefined ? 'anonymous' : undefined}
|
|
|
|
onError={(e) => {
|
2023-03-13 14:25:00 +03:00
|
|
|
if (e.target.crossOrigin) {
|
|
|
|
e.target.crossOrigin = null;
|
|
|
|
e.target.src = url;
|
|
|
|
}
|
2023-03-13 09:24:53 +03:00
|
|
|
}}
|
2023-03-13 05:10:21 +03:00
|
|
|
onLoad={(e) => {
|
2023-03-13 11:22:41 +03:00
|
|
|
if (avatarRef.current) avatarRef.current.dataset.loaded = true;
|
2023-03-13 09:24:53 +03:00
|
|
|
try {
|
|
|
|
// Check if image has alpha channel
|
|
|
|
const canvas = document.createElement('canvas');
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
canvas.width = e.target.width;
|
|
|
|
canvas.height = e.target.height;
|
|
|
|
ctx.drawImage(e.target, 0, 0);
|
|
|
|
const allPixels = ctx.getImageData(
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
canvas.width,
|
|
|
|
canvas.height,
|
|
|
|
);
|
2023-03-15 10:48:26 +03:00
|
|
|
// At least 10% of pixels have alpha <= 128
|
|
|
|
const hasAlpha =
|
|
|
|
allPixels.data.filter((pixel, i) => i % 4 === 3 && pixel <= 128)
|
|
|
|
.length /
|
|
|
|
(allPixels.data.length / 4) >
|
|
|
|
0.1;
|
2023-03-13 09:24:53 +03:00
|
|
|
if (hasAlpha) {
|
2023-03-14 12:32:06 +03:00
|
|
|
// console.log('hasAlpha', hasAlpha, allPixels.data);
|
2023-03-13 09:24:53 +03:00
|
|
|
avatarRef.current.classList.add('has-alpha');
|
|
|
|
alphaCache[url] = true;
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
// Ignore
|
|
|
|
}
|
2023-03-13 05:10:21 +03:00
|
|
|
}}
|
|
|
|
/>
|
2022-12-10 12:14:48 +03:00
|
|
|
)}
|
|
|
|
</span>
|
|
|
|
);
|
2022-12-16 08:27:04 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
export default Avatar;
|