* implement avatar backend functionality * add avatar endpoints * typo * implement client side avatar upload and handling * fixes * Update go/internal/handler/handler.go Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update js/desktop/src/lib/avatar-image.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * bug in order * remove unused component * fix invalid migration * fix syntax errors --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
/**
|
|
* Center-crop an image source to a square and downscale it to a JPEG suitable
|
|
* for an avatar. Avatars never render larger than ~80px, so 512px is generous
|
|
* headroom while keeping the upload to a few tens of KB regardless of input.
|
|
*
|
|
* Pass `mirror` when capturing from a (mirrored) webcam preview so the saved
|
|
* image matches what the user saw.
|
|
*/
|
|
export async function toAvatarBlob(
|
|
source: ImageBitmap,
|
|
{ size = 512, mirror = false }: { size?: number; mirror?: boolean } = {},
|
|
): Promise<Blob> {
|
|
if (!Number.isInteger(size) || size <= 0) {
|
|
throw new Error('Avatar size must be a positive integer');
|
|
}
|
|
const side = Math.min(source.width, source.height);
|
|
if (side === 0) {
|
|
// A not-yet-decoded <video> or a corrupt image yields a zero-size source;
|
|
// cropping it would silently produce a blank avatar, so fail instead.
|
|
throw new Error('Image source has zero dimensions');
|
|
}
|
|
const sx = (source.width - side) / 2;
|
|
const sy = (source.height - side) / 2;
|
|
|
|
const canvas = new OffscreenCanvas(size, size);
|
|
const ctx = canvas.getContext('2d');
|
|
if (!ctx) throw new Error('Failed to acquire 2D canvas context');
|
|
|
|
if (mirror) {
|
|
ctx.translate(size, 0);
|
|
ctx.scale(-1, 1);
|
|
}
|
|
ctx.drawImage(source, sx, sy, side, side, 0, 0, size, size);
|
|
|
|
return canvas.convertToBlob({ type: 'image/jpeg', quality: 0.82 });
|
|
}
|