Skip to content

Commit

Permalink
make feature for increase file size and refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
bnsx committed Jun 9, 2024
1 parent d04eb63 commit 54caed6
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 47 deletions.
7 changes: 6 additions & 1 deletion @types/file.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
export type FileStatus = "wait" | "inprogress" | "done" | "incomplete";
export type FileStatus =
| "wait"
| "inprogress"
| "done"
| "incomplete"
| "nochange";
export type FileState = {
status: FileStatus;
file: File;
Expand Down
49 changes: 26 additions & 23 deletions app/main-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import FormInput from "@/components/FormInput";
import FormSelect from "@/components/FormSelect";
import { useState } from "react";
import { MyDropzone } from "../components/Dropzone";
import { FileState, FileStatus } from "@/@types/file";
import { FileState } from "@/@types/file";
import { ReducerMany, ReturnProps } from "@/lib/reducer";
import { toByte, toMB } from "@/lib/size";
import { toByte } from "@/lib/size";
import { toast } from "sonner";
import UploadedList from "@/components/UploadedList";

Expand All @@ -36,7 +36,10 @@ const unit_data = [
{ label: "KB", value: "kb" },
{ label: "MB", value: "mb" },
];

const type_data = [
{ label: "ลดขนาดไฟล์", value: "reduce" },
{ label: "เพิ่มขนาดไฟล์", value: "boost" },
];
export default function MainForm() {
const [files, setFiles] = useState<FileState[]>([]);
const [isSubmit, setSubmit] = useState<boolean>(false);
Expand All @@ -49,10 +52,8 @@ export default function MainForm() {
file: FileState,
reduced: ReturnProps[]
): FileState => {
const compressedFile = reduced.find(
(z) => z.blobURL === file.blobURL && z.status === "done"
);
if (compressedFile) {
const compressedFile = reduced.filter((z) => z.blobURL === file.blobURL)[0];
if (compressedFile.status === "done") {
return {
...file,
newFile: compressedFile.newFile,
Expand All @@ -61,7 +62,11 @@ export default function MainForm() {
status: compressedFile.status,
};
}
return { ...file, status: "incomplete" as FileStatus, savedPercent: 0 };
return {
...file,
savedPercent: compressedFile.savedPercent,
status: compressedFile.status,
};
};
const setCompressingPercent = (blobURL: string, progress: number) => {
setFiles((prev) =>
Expand All @@ -79,12 +84,15 @@ export default function MainForm() {
if (files.length === 0) {
return toast.error("โปรดอัพโหลดภาพ");
}
if (files.every((x) => x.status === "done" || x.status === "nochange")) {
return;
}
try {
setSubmit(true);
const maxSize = toMB(value.unit, value.maxSize);
const maxSize = toByte(value.unit, value.maxSize);
const reduced = await ReducerMany(
files.filter((x) => x.status !== "done"),
minSize,
value.type,
maxSize,
setCompressingPercent
);
Expand All @@ -94,10 +102,7 @@ export default function MainForm() {
}
return compressedToDoUpdate(file, reduced);
});

setFiles(updatedFiles);
} catch (error) {
console.log(error);
} finally {
setSubmit(false);
}
Expand All @@ -124,26 +129,24 @@ export default function MainForm() {
<FormInput
control={form.control}
schema={schema}
name={"minSize"}
label="ขนาดไฟล์ต่ำสุด (Min Size)"
name={"maxSize"}
label="ขนาดไฟล์สูงสุด (Max Size)"
placeholder="ป้อนขนาดไฟล์ที่ต้องการไม่ให้เกิน"
className="w-full"
/>
<FormInput
<FormSelect
control={form.control}
schema={schema}
name={"maxSize"}
label="ขนาดไฟล์สูงสุด (Max Size)"
placeholder="ป้อนขนาดไฟล์ที่ต้องการไม่ให้เกิน"
className="w-full"
name={"unit"}
data={unit_data}
/>
</div>
<FormSelect
control={form.control}
schema={schema}
name={"unit"}
data={unit_data}
label="หน่วย KB / MB"
name={"type"}
data={type_data}
label="เพิ่ม / ลด"
/>
</CardContent>
<CardFooter>
Expand Down
2 changes: 1 addition & 1 deletion components/UploadedList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default function UploadedList({ files, removeFile }: Props) {
<Badge className="text-xs w-fit" variant={"outline"}>
{handleStatusUpdate(obj.status)}
</Badge>
{obj.status === "done" && (
{(obj.status === "done" || obj.status === "nochange") && (
<Badge className="text-xs" variant={"outline"}>
ประหยัด {obj.savedPercent}%
</Badge>
Expand Down
34 changes: 20 additions & 14 deletions lib/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface ReducerProps {
}
interface BoosterProps {
data: FileState;
maxSizeMB: number;
maxSize: number;
fileType?: string;
setCompressingPercent: (blobURL: string, percent: number) => void;
}
Expand Down Expand Up @@ -79,51 +79,57 @@ export async function Reducer({
export async function ReducerMany(
imageFiles: FileState[],
type: "reduce" | "boost",
maxSizeMB: number,
maxSize: number,
setCompressingPercent: (blobURL: string, percent: number) => void
) {
): Promise<ReturnProps[]> {
return await Promise.all(
imageFiles.map((imageFile) => {
if (type === "reduce") {
return Reducer({
if (type === "boost") {
return Booster({
data: imageFile,
maxSizeMB,
maxSize,
setCompressingPercent,
});
}
return Booster({
return Reducer({
data: imageFile,
maxSizeMB,
maxSizeMB: toMB("byte", maxSize),
setCompressingPercent,
});
})
);
}
export function Booster({
data,
maxSizeMB,
maxSize,
fileType = "image/jpeg",
setCompressingPercent,
}: BoosterProps): ReturnProps {
if (data.file.size > maxSize) {
setCompressingPercent(data.blobURL, 100);
return { ...data, status: "nochange", savedPercent: 0 };
}
const currentSizeMB = toMB("byte", data.file.size);
const sizeDifferenceMB = maxSizeMB - currentSizeMB;
const sizeDifferenceMB = toMB("byte", maxSize) - currentSizeMB;

if (sizeDifferenceMB <= 0) {
// No need to increase size if the new size is smaller than or equal to the original size
return { ...data, savedPercent: 0 }; // Return data with savedPercent as 0
return { ...data, status: "nochange", savedPercent: 0 }; // Return data with savedPercent as 0
}

// Create a Uint8Array buffer with the desired size difference
const buffer = new Uint8Array(sizeDifferenceMB * 1024 * 1024);
const timestamp = Date.now();
const newFilename = `boosted_${timestamp}`;

// Create a new File object with the original file's data and the additional buffer
const newFile = new File([data.file, buffer], data.file.name, {
const newFile = new File([data.file, buffer], newFilename, {
type: fileType,
lastModified: Date.now(),
lastModified: timestamp,
});

// Set the saved percent to 100 since we're effectively adding the entire difference
setCompressingPercent(data.blobURL, 100);

return { ...data, status: "done", savedPercent: 100, newFile };
return { ...data, status: "done", savedPercent: 0, newFile };
}
28 changes: 20 additions & 8 deletions lib/size.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
export const computeSize = (unit: "kb" | "mb", value: number): number => {
// Define conversion factors
const KB_TO_MB = 1 / 1024; // 1 KB is 1/1024 MB

export const toKB = (unit: "kb" | "mb", value: number): number => {
if (unit === "mb") {
return value * 1024;
}
return value;
};
export const toMB = (unit: "kb" | "mb" | "byte", value: number): number => {
if (unit === "kb") {
return value * KB_TO_MB;
return value / 1024;
}
if (unit === "byte") {
return value / (1024 * 1024);
}
return value;
};
export const toByte = (unit: "kb" | "mb", value: number): number => {
if (unit === "kb") {
return value * 1024;
}
return value * 1024 * 1024;
};
export function formatFileSize(size: number): string {
if (size < 1024) {
return `${size} Byte`;
} else if (size < 1024 * 1024) {
}
if (size < 1024 * 1024) {
return `${(size / 1024).toFixed(2)} KB`;
} else {
return `${(size / (1024 * 1024)).toFixed(2)} MB`;
}
return `${(size / (1024 * 1024)).toFixed(2)} MB`;
}
1 change: 1 addition & 0 deletions lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const statusTranslations: Record<FileStatus, string> = {
inprogress: "กำลังทำงาน",
done: "เสร็จสิ้น",
incomplete: "เกิดข้อผิดพลาด",
nochange: "ไม่เปลี่ยนแปลง",
};

export const handleStatusUpdate = (status: FileStatus): string => {
Expand Down

0 comments on commit 54caed6

Please sign in to comment.