Auto-generate blur data when editing photos
This commit is contained in:
parent
afd0e23a67
commit
af0b004a79
@ -1,24 +1,17 @@
|
||||
import Link from 'next/link';
|
||||
import PathLoaderButton from '@/components/PathLoaderButton';
|
||||
import { FaRegEdit } from 'react-icons/fa';
|
||||
|
||||
export default function EditButton ({
|
||||
href,
|
||||
label = 'Edit',
|
||||
}: {
|
||||
href: string,
|
||||
label?: string,
|
||||
}) {
|
||||
return (
|
||||
<Link
|
||||
title={label}
|
||||
href={href}
|
||||
className="button"
|
||||
prefetch={false}
|
||||
<PathLoaderButton
|
||||
path={href}
|
||||
icon={<FaRegEdit size={15} className="translate-y-[0.5px]" />}
|
||||
>
|
||||
<FaRegEdit className="translate-y-[-0.5px]" />
|
||||
<span className="hidden sm:inline-block">
|
||||
{label}
|
||||
</span>
|
||||
</Link>
|
||||
Edit
|
||||
</PathLoaderButton>
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,8 +3,8 @@ import { getPhotoNoStore, getUniqueTagsCached } from '@/photo/cache';
|
||||
import { PATH_ADMIN } from '@/site/paths';
|
||||
import PhotoEditPageClient from '@/photo/PhotoEditPageClient';
|
||||
import { AI_TEXT_GENERATION_ENABLED } from '@/site/config';
|
||||
import { resizeImageFromUrl } from '@/photo/server';
|
||||
import { getNextImageUrlForRequest } from '@/services/next-image';
|
||||
import { blurImageFromUrl, resizeImageFromUrl } from '@/photo/server';
|
||||
import { getNextImageUrlForManipulation } from '@/services/next-image';
|
||||
|
||||
export default async function PhotoEditPage({
|
||||
params: { photoId },
|
||||
@ -21,15 +21,20 @@ export default async function PhotoEditPage({
|
||||
|
||||
// Only generate image thumbnails when AI generation is enabled
|
||||
const imageThumbnailBase64 = AI_TEXT_GENERATION_ENABLED
|
||||
? await resizeImageFromUrl(getNextImageUrlForRequest(photo.url, 640))
|
||||
? await resizeImageFromUrl(getNextImageUrlForManipulation(photo.url))
|
||||
: '';
|
||||
|
||||
const blurData = await blurImageFromUrl(
|
||||
getNextImageUrlForManipulation(photo.url)
|
||||
);
|
||||
|
||||
return (
|
||||
<PhotoEditPageClient {...{
|
||||
photo,
|
||||
uniqueTags,
|
||||
hasAiTextGeneration,
|
||||
imageThumbnailBase64,
|
||||
blurData,
|
||||
}} />
|
||||
);
|
||||
};
|
||||
|
||||
@ -22,11 +22,13 @@ export default function PhotoEditPageClient({
|
||||
uniqueTags,
|
||||
hasAiTextGeneration,
|
||||
imageThumbnailBase64,
|
||||
blurData,
|
||||
}: {
|
||||
photo: Photo
|
||||
uniqueTags: TagsWithMeta
|
||||
hasAiTextGeneration: boolean
|
||||
imageThumbnailBase64: string
|
||||
blurData: string
|
||||
}) {
|
||||
const seedExifData = { url: photo.url };
|
||||
|
||||
@ -86,6 +88,7 @@ export default function PhotoEditPageClient({
|
||||
updatedExifData={hasExifDataBeenFound
|
||||
? updatedExifData
|
||||
: undefined}
|
||||
updatedBlurData={blurData}
|
||||
uniqueTags={uniqueTags}
|
||||
aiContent={hasAiTextGeneration ? aiContent : undefined}
|
||||
onTitleChange={setUpdatedTitle}
|
||||
|
||||
@ -27,22 +27,25 @@ import Spinner from '@/components/Spinner';
|
||||
import usePreventNavigation from '@/utility/usePreventNavigation';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import UpdateBlurDataButton from '../UpdateBlurDataButton';
|
||||
import { getNextImageUrlForManipulation } from '@/services/next-image';
|
||||
|
||||
const THUMBNAIL_SIZE = 300;
|
||||
|
||||
export default function PhotoForm({
|
||||
type = 'create',
|
||||
initialPhotoForm,
|
||||
updatedExifData,
|
||||
type = 'create',
|
||||
updatedBlurData,
|
||||
uniqueTags,
|
||||
aiContent,
|
||||
onTitleChange,
|
||||
onTextContentChange,
|
||||
onFormStatusChange,
|
||||
}: {
|
||||
type?: 'create' | 'edit'
|
||||
initialPhotoForm: Partial<PhotoFormData>
|
||||
updatedExifData?: Partial<PhotoFormData>
|
||||
type?: 'create' | 'edit'
|
||||
updatedBlurData?: string
|
||||
uniqueTags?: TagsWithMeta
|
||||
aiContent?: AiContent
|
||||
onTitleChange?: (updatedTitle: string) => void
|
||||
@ -110,6 +113,12 @@ export default function PhotoForm({
|
||||
|
||||
const url = formData.url ?? '';
|
||||
|
||||
useEffect(() =>
|
||||
setFormData(data => updatedBlurData
|
||||
? { ...data, blurData: updatedBlurData }
|
||||
: data)
|
||||
, [updatedBlurData]);
|
||||
|
||||
useEffect(() =>
|
||||
setFormData(data => aiContent?.title
|
||||
? { ...data, title: aiContent?.title }
|
||||
@ -184,9 +193,9 @@ export default function PhotoForm({
|
||||
shouldConfirm={Boolean(formData.semanticDescription)}
|
||||
/>;
|
||||
case 'blurData':
|
||||
return type === 'edit'
|
||||
return shouldDebugBlur && type === 'edit' && formData.url
|
||||
? <UpdateBlurDataButton
|
||||
photoUrl={formData.url}
|
||||
photoUrl={getNextImageUrlForManipulation(formData.url)}
|
||||
onUpdatedBlurData={blurData =>
|
||||
setFormData(data => ({ ...data, blurData }))}
|
||||
/>
|
||||
|
||||
@ -23,3 +23,8 @@ export const getNextImageUrlForRequest = (
|
||||
|
||||
return url.toString();
|
||||
};
|
||||
|
||||
// Generate small, low-bandwidth images for quick manipulations such as
|
||||
// generating blur data or image thumbnails for AI text generation
|
||||
export const getNextImageUrlForManipulation = (imageUrl: string) =>
|
||||
getNextImageUrlForRequest(imageUrl, 640, 90);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user