Skip to content

Commit c5db29e

Browse files
committed
feat: Profile Image resizing
1 parent d12f949 commit c5db29e

File tree

4 files changed

+51
-10
lines changed

4 files changed

+51
-10
lines changed

src/components/account/profile/ImageUpload.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Button } from '@heroui/button';
22
import { uploadProfileImage } from '@lib/api/backend';
3+
import { resizeImage } from '@lib/utils';
34
import { useCallback, useRef } from 'react';
45
import toast from 'react-hot-toast';
56

@@ -16,17 +17,16 @@ export default function ImageUpload({
1617
async (event: React.ChangeEvent<HTMLInputElement>) => {
1718
setImageLoading(true);
1819

19-
const file = event.target.files?.[0];
20+
let file: File | undefined = event.target.files?.[0];
2021

2122
if (!file) {
2223
return;
2324
}
2425

25-
if (file.size > 500_000) {
26-
const message = 'Image size must not exceed 500 KB.';
27-
toast.error(message);
28-
event.target.value = '';
29-
return;
26+
if (file.size > 50_000) {
27+
const resizedBlob = await resizeImage(file);
28+
console.log('Resized size (KB):', resizedBlob.size / 1024);
29+
file = new File([resizedBlob], file.name, { type: 'image/jpeg' });
3030
}
3131

3232
try {

src/lib/api/backend.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ export const initSumsubSession = (type: 'individual' | 'company') => _doPost<str
105105
export const getPublicProfileInfo = async (address: types.EthAddress) =>
106106
_doPost<any>('/branding/get-brands', { brandAddresses: [address] });
107107

108-
export const uploadProfileImage = async (logo: File) => {
108+
export const uploadProfileImage = async (file: File) => {
109109
const formData = new FormData();
110-
formData.append('logo', logo);
110+
formData.append('logo', file);
111111

112112
return _doPost<any>('/branding/edit-logo', formData, {
113113
'Content-Type': 'multipart/form-data',

src/lib/utils.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,44 @@ export function parseIfJson<T = any>(input: string): T | string {
141141
return input;
142142
}
143143
}
144+
145+
export function resizeImage(file: File, maxWidth = 512, maxHeight = 512, quality = 0.9): Promise<Blob> {
146+
return new Promise((resolve, reject) => {
147+
const img = new Image();
148+
img.onload = () => {
149+
let { width, height } = img;
150+
151+
// Maintain aspect ratio
152+
if (width > height) {
153+
if (width > maxWidth) {
154+
height *= maxWidth / width;
155+
width = maxWidth;
156+
}
157+
} else {
158+
if (height > maxHeight) {
159+
width *= maxHeight / height;
160+
height = maxHeight;
161+
}
162+
}
163+
164+
const canvas = document.createElement('canvas');
165+
canvas.width = width;
166+
canvas.height = height;
167+
const ctx = canvas.getContext('2d');
168+
if (!ctx) return reject(new Error('No canvas context'));
169+
170+
ctx.drawImage(img, 0, 0, width, height);
171+
172+
canvas.toBlob(
173+
(blob) => {
174+
if (!blob) return reject(new Error('Canvas toBlob failed'));
175+
resolve(blob);
176+
},
177+
'image/jpeg',
178+
quality, // Between 0 and 1
179+
);
180+
};
181+
img.onerror = reject;
182+
img.src = URL.createObjectURL(file);
183+
});
184+
}

src/schemas/profile.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import z from 'zod';
2-
import { getOptionalStringWithSpacesSchema, getStringSchema } from './common';
2+
import { getOptionalStringWithSpacesSchema } from './common';
33

44
export const buildPublicProfileSchema = (brandingPlatforms: string[]) => {
55
const shape: Record<string, z.ZodType> = {};
@@ -9,7 +9,7 @@ export const buildPublicProfileSchema = (brandingPlatforms: string[]) => {
99
}
1010

1111
return z.object({
12-
name: getStringSchema(3, 32),
12+
name: getOptionalStringWithSpacesSchema(3, 32),
1313
description: getOptionalStringWithSpacesSchema(0, 80),
1414
links: z.object(shape),
1515
});

0 commit comments

Comments
 (0)