mirror of
https://github.com/AmruthPillai/Reactive-Resume.git
synced 2026-07-27 18:34:51 +10:00
refactor(web): finding 6 - remove useQuery picture preview fetch
The uploads endpoint is public (Cache-Control: public, no auth headers), so a plain img src suffices. Remove createPicturePreviewUrl, the useQuery call, and the object-URL cleanup useEffect; simplify PicturePreviewControls to use normalizedPictureUrl directly. Claude-Session: https://claude.ai/code/session_012Bnvt1MghwHj4qQRxuQUGa
This commit is contained in:
@@ -10,8 +10,8 @@ import {
|
|||||||
TrashSimpleIcon,
|
TrashSimpleIcon,
|
||||||
UploadSimpleIcon,
|
UploadSimpleIcon,
|
||||||
} from "@phosphor-icons/react";
|
} from "@phosphor-icons/react";
|
||||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
import Cropper from "react-easy-crop";
|
import Cropper from "react-easy-crop";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { pictureSchema } from "@reactive-resume/schema/resume/data";
|
import { pictureSchema } from "@reactive-resume/schema/resume/data";
|
||||||
@@ -56,7 +56,6 @@ type PicturePreviewControlsProps = {
|
|||||||
form: PictureSettingsForm;
|
form: PictureSettingsForm;
|
||||||
normalizedPictureUrl: string;
|
normalizedPictureUrl: string;
|
||||||
picture: PictureValues;
|
picture: PictureValues;
|
||||||
pictureSrc: string;
|
|
||||||
onAutoSave: () => void;
|
onAutoSave: () => void;
|
||||||
onDeletePicture: () => void;
|
onDeletePicture: () => void;
|
||||||
onSelectPicture: () => void;
|
onSelectPicture: () => void;
|
||||||
@@ -68,7 +67,6 @@ function PicturePreviewControls({
|
|||||||
form,
|
form,
|
||||||
normalizedPictureUrl,
|
normalizedPictureUrl,
|
||||||
picture,
|
picture,
|
||||||
pictureSrc,
|
|
||||||
onAutoSave,
|
onAutoSave,
|
||||||
onDeletePicture,
|
onDeletePicture,
|
||||||
onSelectPicture,
|
onSelectPicture,
|
||||||
@@ -91,10 +89,10 @@ function PicturePreviewControls({
|
|||||||
aria-label={picture.url ? t`Delete picture` : t`Upload picture`}
|
aria-label={picture.url ? t`Delete picture` : t`Upload picture`}
|
||||||
className="group/picture relative size-18 cursor-pointer overflow-hidden rounded-md bg-secondary transition-colors hover:bg-secondary/50"
|
className="group/picture relative size-18 cursor-pointer overflow-hidden rounded-md bg-secondary transition-colors hover:bg-secondary/50"
|
||||||
>
|
>
|
||||||
{(pictureSrc || normalizedPictureUrl) && (
|
{normalizedPictureUrl && (
|
||||||
<img
|
<img
|
||||||
alt=""
|
alt=""
|
||||||
src={pictureSrc || normalizedPictureUrl}
|
src={normalizedPictureUrl}
|
||||||
className="fade-in relative z-10 size-full animate-in rounded-md object-cover transition-opacity group-hover/picture:opacity-20"
|
className="fade-in relative z-10 size-full animate-in rounded-md object-cover transition-opacity group-hover/picture:opacity-20"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -420,17 +418,6 @@ async function getCroppedImageBlob(imageSrc: string, pixelCrop: Area): Promise<B
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createPicturePreviewUrl(url: string, signal: AbortSignal) {
|
|
||||||
const response = await fetch(url, { signal });
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Failed to fetch image: ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const blob = await response.blob();
|
|
||||||
return URL.createObjectURL(blob);
|
|
||||||
}
|
|
||||||
|
|
||||||
function usePictureSettingsForm(picture: PictureValues, persist: (data: PictureValues) => void) {
|
function usePictureSettingsForm(picture: PictureValues, persist: (data: PictureValues) => void) {
|
||||||
const form = useAppForm({
|
const form = useAppForm({
|
||||||
defaultValues: picture,
|
defaultValues: picture,
|
||||||
@@ -463,13 +450,6 @@ function PictureSectionForm() {
|
|||||||
const resume = useCurrentResume();
|
const resume = useCurrentResume();
|
||||||
const picture = resume.data.picture;
|
const picture = resume.data.picture;
|
||||||
const normalizedPictureUrl = normalizePictureUrl(picture.url, appOrigin);
|
const normalizedPictureUrl = normalizePictureUrl(picture.url, appOrigin);
|
||||||
const picturePreviewQuery = useQuery({
|
|
||||||
queryKey: ["resume-picture-preview", normalizedPictureUrl],
|
|
||||||
queryFn: ({ signal }) => createPicturePreviewUrl(normalizedPictureUrl, signal),
|
|
||||||
enabled: Boolean(normalizedPictureUrl),
|
|
||||||
gcTime: 0,
|
|
||||||
});
|
|
||||||
const pictureSrc = picturePreviewQuery.data ?? normalizedPictureUrl;
|
|
||||||
const updateResumeData = useUpdateResumeData();
|
const updateResumeData = useUpdateResumeData();
|
||||||
|
|
||||||
const { mutate: uploadFile } = useMutation(orpc.storage.uploadFile.mutationOptions({ meta: { noInvalidate: true } }));
|
const { mutate: uploadFile } = useMutation(orpc.storage.uploadFile.mutationOptions({ meta: { noInvalidate: true } }));
|
||||||
@@ -569,14 +549,6 @@ function PictureSectionForm() {
|
|||||||
closeCropDialog();
|
closeCropDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const objectUrl = picturePreviewQuery.data;
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (objectUrl) URL.revokeObjectURL(objectUrl);
|
|
||||||
};
|
|
||||||
}, [picturePreviewQuery.data]);
|
|
||||||
|
|
||||||
const cropAspect = Number(form.state.values.aspectRatio) || 1;
|
const cropAspect = Number(form.state.values.aspectRatio) || 1;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -665,7 +637,6 @@ function PictureSectionForm() {
|
|||||||
form={form}
|
form={form}
|
||||||
normalizedPictureUrl={normalizedPictureUrl}
|
normalizedPictureUrl={normalizedPictureUrl}
|
||||||
picture={picture}
|
picture={picture}
|
||||||
pictureSrc={pictureSrc}
|
|
||||||
onAutoSave={handleAutoSave}
|
onAutoSave={handleAutoSave}
|
||||||
onDeletePicture={onDeletePicture}
|
onDeletePicture={onDeletePicture}
|
||||||
onSelectPicture={onSelectPicture}
|
onSelectPicture={onSelectPicture}
|
||||||
|
|||||||
Reference in New Issue
Block a user