Skip to content

Commit

Permalink
feat: drop exif data and compress image max to 2048hw/1mb (#4171)
Browse files Browse the repository at this point in the history
  • Loading branch information
bigint committed Dec 11, 2023
1 parent bd797d6 commit 59a0947
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 72 deletions.
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@tippyjs/react": "^4.2.6",
"@wagmi/connectors": "^3.1.8",
"axios": "^1.6.2",
"browser-image-compression": "^2.0.2",
"dayjs": "^1.11.10",
"dayjs-twitter": "^0.5.0",
"dotenv": "^16.3.1",
Expand Down
169 changes: 97 additions & 72 deletions apps/web/src/hooks/useUploadAttachments.tsx
Original file line number Diff line number Diff line change
@@ -1,104 +1,129 @@
import type { NewAttachment } from '@hey/types/misc';

import uploadToIPFS from '@lib/uploadToIPFS';
import imageCompression from 'browser-image-compression';
import { useCallback } from 'react';
import { toast } from 'react-hot-toast';
import { usePublicationStore } from 'src/store/non-persisted/usePublicationStore';
import { v4 as uuid } from 'uuid';

const useUploadAttachments = () => {
const addAttachments = usePublicationStore((state) => state.addAttachments);
const updateAttachments = usePublicationStore(
(state) => state.updateAttachments
);
const removeAttachments = usePublicationStore(
(state) => state.removeAttachments
);
const setIsUploading = usePublicationStore((state) => state.setIsUploading);
const setUploadedPercentage = usePublicationStore(
(state) => state.setUploadedPercentage
);
const {
addAttachments,
removeAttachments,
setIsUploading,
setUploadedPercentage,
updateAttachments
} = usePublicationStore((state) => ({
addAttachments: state.addAttachments,
removeAttachments: state.removeAttachments,
setIsUploading: state.setIsUploading,
setUploadedPercentage: state.setUploadedPercentage,
updateAttachments: state.updateAttachments
}));

const validateFileSize = (file: any) => {
const isImage = file.type.includes('image');
const isVideo = file.type.includes('video');
const isAudio = file.type.includes('audio');

if (isImage && file.size > 50000000) {
toast.error('Image size should be less than 50MB');
return false;
}

if (isVideo && file.size > 500000000) {
toast.error('Video size should be less than 500MB');
return false;
}

if (isAudio && file.size > 200000000) {
toast.error('Audio size should be less than 200MB');
return false;
}

return true;
};

const handleUploadAttachments = useCallback(
async (attachments: any): Promise<NewAttachment[]> => {
setIsUploading(true);

const files = Array.from(attachments);
const attachmentIds: string[] = [];

const previewAttachments: NewAttachment[] = files.map((file: any) => {
const attachmentId = uuid();
attachmentIds.push(attachmentId);

return {
file,
id: attachmentId,
mimeType: file.type,
previewUri: URL.createObjectURL(file),
type: file.type.includes('image')
? 'Image'
: file.type.includes('video')
? 'Video'
: 'Audio',
uri: URL.createObjectURL(file)
};
});

const hasLargeAttachment = files.map((file: any) => {
const isImage = file.type.includes('image');
const isVideo = file.type.includes('video');
const isAudio = file.type.includes('audio');

if (isImage && file.size > 50000000) {
toast.error('Image size should be less than 50MB');
return false;
}
const compressedFiles = await Promise.all(
files.map(async (file: any) => {
if (file.type.includes('image')) {
return await imageCompression(file, {
exifOrientation: 1,
maxSizeMB: 1,
maxWidthOrHeight: 2048,
useWebWorker: true
});
}
return file;
})
);

if (isVideo && file.size > 500000000) {
toast.error('Video size should be less than 500MB');
return false;
}
const previewAttachments: NewAttachment[] = compressedFiles.map(
(file: any) => {
const attachmentId = uuid();
attachmentIds.push(attachmentId);

if (isAudio && file.size > 100000000) {
toast.error('Audio size should be less than 100MB');
return false;
return {
file,
id: attachmentId,
mimeType: file.type,
previewUri: URL.createObjectURL(file),
type: file.type.includes('image')
? 'Image'
: file.type.includes('video')
? 'Video'
: 'Audio',
uri: URL.createObjectURL(file)
};
}
);

return true;
});
if (compressedFiles.some((file) => validateFileSize(file))) {
addAttachments(previewAttachments);

addAttachments(previewAttachments);
let attachmentsIPFS: NewAttachment[] = [];
try {
if (hasLargeAttachment.includes(false)) {
setIsUploading(false);
removeAttachments(attachmentIds);
return [];
}

const attachmentsUploaded = await uploadToIPFS(
attachments,
(percentCompleted) => setUploadedPercentage(percentCompleted)
);
if (attachmentsUploaded) {
attachmentsIPFS = previewAttachments.map(
(attachment: NewAttachment, index: number) => ({
...attachment,
mimeType: attachmentsUploaded[index].mimeType,
uri: attachmentsUploaded[index].uri
try {
const attachmentsUploaded = await uploadToIPFS(
compressedFiles,
setUploadedPercentage
);
const attachmentsIPFS = attachmentsUploaded.map(
(uploaded, index) => ({
...previewAttachments[index],
mimeType: uploaded.mimeType,
uri: uploaded.uri
})
);

updateAttachments(attachmentsIPFS);
setIsUploading(false);
return attachmentsIPFS;
} catch (error) {
console.error(error);
toast.error('Something went wrong while uploading!');
removeAttachments(attachmentIds);
}
} catch {
} else {
removeAttachments(attachmentIds);
toast.error('Something went wrong while uploading!');
}
setIsUploading(false);

return attachmentsIPFS;
setIsUploading(false);
return [];
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[addAttachments, removeAttachments, updateAttachments, setIsUploading]
[
addAttachments,
removeAttachments,
updateAttachments,
setIsUploading,
setUploadedPercentage
]
);

return { handleUploadAttachments };
Expand Down
18 changes: 18 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 comment on commit 59a0947

@vercel
Copy link

@vercel vercel bot commented on 59a0947 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

web – ./

web-git-main-heyxyz.vercel.app
heyxyz.vercel.app
web-heyxyz.vercel.app
hey.xyz

Please sign in to comment.