@replyke/core
Version:
Replyke: Build interactive apps with social features like comments, votes, feeds, user lists, notifications, and more.
106 lines • 4.22 kB
JavaScript
import { useCallback, useState } from "react";
import useAxiosPrivate from "../../config/useAxiosPrivate";
import useProject from "../projects/useProject";
// Type guard to detect browser File vs React Native file object
function isBrowserFile(file) {
return typeof File !== "undefined" && file instanceof File;
}
function useUploadImage() {
const axios = useAxiosPrivate();
const { projectId } = useProject();
const [uploading, setUploading] = useState(false);
const [progress, setProgress] = useState(0);
const uploadImage = useCallback(async (file, options) => {
// Validate required inputs
if (!projectId) {
throw new Error("No projectId available.");
}
if (!file) {
throw new Error("No file provided.");
}
setUploading(true);
setProgress(0);
try {
const formData = new FormData();
// Append file (handle both browser and React Native)
if (isBrowserFile(file)) {
formData.append("file", file, file.name);
}
else {
formData.append("file", {
uri: file.uri,
type: file.type || "image/jpeg",
name: file.name,
});
}
// Append mode (required)
formData.append("mode", options.mode);
// Append mode-specific fields
if (options.mode === "exact-dimensions") {
formData.append("dimensions", JSON.stringify(options.dimensions));
}
else if (options.mode === "aspect-ratio-width-based") {
formData.append("aspectRatio", JSON.stringify(options.aspectRatio));
formData.append("widths", JSON.stringify(options.widths));
}
else if (options.mode === "aspect-ratio-height-based") {
formData.append("aspectRatio", JSON.stringify(options.aspectRatio));
formData.append("heights", JSON.stringify(options.heights));
}
else if (options.mode === "original-aspect") {
formData.append("sizes", JSON.stringify(options.sizes));
}
// Append common optional fields
if (options.pathParts) {
formData.append("pathParts", JSON.stringify(options.pathParts));
}
if (options.quality !== undefined) {
formData.append("quality", options.quality.toString());
}
if (options.format) {
formData.append("format", options.format);
}
if (options.stripExif !== undefined) {
formData.append("stripExif", options.stripExif.toString());
}
if (options.fit) {
formData.append("fit", options.fit);
}
// Append optional associations
if (options.entityId) {
formData.append("entityId", options.entityId);
}
if (options.commentId) {
formData.append("commentId", options.commentId);
}
if (options.spaceId) {
formData.append("spaceId", options.spaceId);
}
// Make request with progress tracking
const response = await axios.post(`/${projectId}/storage/images`, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
onUploadProgress: (progressEvent) => {
if (progressEvent.total) {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
setProgress(percentCompleted);
options.onProgress?.(percentCompleted);
}
},
});
return response.data;
}
finally {
setUploading(false);
setProgress(0);
}
}, [projectId, axios]);
return {
uploadImage,
uploading,
progress,
};
}
export default useUploadImage;
//# sourceMappingURL=useUploadImage.js.map