Refine file download behavior

This commit is contained in:
Sam Becker 2024-09-21 15:26:11 -05:00
parent 0dc627b774
commit d3c8db474e
4 changed files with 30 additions and 25 deletions

View File

@ -4,7 +4,11 @@ import { ComponentProps, useMemo } from 'react';
import { pathForAdminPhotoEdit, pathForPhoto } from '@/site/paths';
import { deletePhotoAction, toggleFavoritePhotoAction } from '@/photo/actions';
import { FaRegEdit, FaRegStar, FaStar } from 'react-icons/fa';
import { Photo, deleteConfirmationTextForPhoto } from '@/photo';
import {
Photo,
deleteConfirmationTextForPhoto,
downloadFileNameForPhoto,
} from '@/photo';
import { isPathFavs, isPhotoFav } from '@/tag';
import { usePathname } from 'next/navigation';
import { BiTrash } from 'react-icons/bi';
@ -64,7 +68,7 @@ export default function AdminPhotoMenuClient({
className="translate-x-[-1.5px] translate-y-[-0.5px]"
/>,
href: photo.url,
hrefDownloadName: photo.url.split('/').pop(),
hrefDownloadName: downloadFileNameForPhoto(photo),
});
items.push({
label: 'Delete',

View File

@ -1,7 +1,8 @@
import { MdOutlineFileDownload } from 'react-icons/md';
import PathLoaderButton from './primitives/PathLoaderButton';
import { clsx } from 'clsx/lite';
import { Photo } from '@/photo';
import { downloadFileNameForPhoto, Photo } from '@/photo';
import LoaderButton from './primitives/LoaderButton';
import { useState } from 'react';
export default function DownloadButton({
photo,
@ -12,30 +13,30 @@ export default function DownloadButton({
dim?: boolean
className?: string
}) {
const {url, title} = photo;
const [isLoading, setIsLoading] = useState(false);
return (
<PathLoaderButton
path={url}
<LoaderButton
title="Download Original File"
className={clsx(
className,
dim ? 'text-dim' : 'text-medium',
'-mx-0.5 translate-x-0.5',
'sm:mx-0 sm:translate-x-0'
)}
icon={<MdOutlineFileDownload size={16} />}
icon={<MdOutlineFileDownload size={18} />}
spinnerColor='dim'
styleAs='link'
shouldReplace
handleAction={async () => {
const response = await fetch(url);
const blob = await response.blob();
isLoading={isLoading}
onClick={async () => {
setIsLoading(true);
const blob = await fetch(photo.url)
.then(response => response.blob())
.finally(() => setIsLoading(false));
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = title
? title.replace(/[^a-z0-9]/gi, '_').toLowerCase()
: url.split('/').pop() || 'download';
link.download = downloadFileNameForPhoto(photo);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

View File

@ -10,7 +10,6 @@ export default function PathLoaderButton({
loaderDelay = 100,
shouldScroll = true,
shouldReplace,
handleAction,
children,
...props
}: {
@ -19,7 +18,6 @@ export default function PathLoaderButton({
loaderDelay?: number
shouldScroll?: boolean
shouldReplace?: boolean
handleAction?: () => Promise<void>
} & ComponentProps<typeof LoaderButton>) {
const router = useRouter();
@ -48,15 +46,11 @@ export default function PathLoaderButton({
<LoaderButton
{...props}
onClick={() => {
startTransition(async () => {
if (handleAction) {
await handleAction();
startTransition(() => {
if (shouldReplace) {
router.replace(path, { scroll: shouldScroll });
} else {
if (shouldReplace) {
router.replace(path, { scroll: shouldScroll });
} else {
router.push(path, { scroll: shouldScroll });
}
router.push(path, { scroll: shouldScroll });
}
});
}}

View File

@ -12,6 +12,7 @@ import {
formatExposureCompensation,
formatExposureTime,
} from '@/utility/exif';
import { parameterize } from '@/utility/string';
import camelcaseKeys from 'camelcase-keys';
import { isBefore } from 'date-fns';
import type { Metadata } from 'next';
@ -311,5 +312,10 @@ export const isNextImageReadyBasedOnPhotos = async (photos: Photo[]) =>
.then(response => response.ok)
.catch(() => false);
export const downloadFileNameForPhoto = (photo: Photo) =>
photo.title
? `${parameterize(photo.title)}.${photo.extension}`
: photo.url.split('/').pop() || 'download';
export const doesPhotoNeedBlurCompatibility = (photo: Photo) =>
isBefore(photo.updatedAt, new Date('2024-05-07'));