diff --git a/src/admin/AdminPhotoMenuClient.tsx b/src/admin/AdminPhotoMenuClient.tsx index 99154499..892ae04e 100644 --- a/src/admin/AdminPhotoMenuClient.tsx +++ b/src/admin/AdminPhotoMenuClient.tsx @@ -11,6 +11,7 @@ import { BiTrash } from 'react-icons/bi'; import MoreMenu, { MoreMenuItem } from '@/components/more/MoreMenu'; import { useAppState } from '@/state/AppState'; import { RevalidatePhoto } from '@/photo/InfinitePhotoScroll'; +import { MdOutlineFileDownload } from 'react-icons/md'; export default function AdminPhotoMenuClient({ photo, @@ -29,7 +30,7 @@ export default function AdminPhotoMenuClient({ const shouldRedirectFav = isPathFavs(path) && isFav; const shouldRedirectDelete = pathForPhoto({ photo: photo.id }) === path; - const favIconClass = 'translate-x-[-1.5px] translate-y-[0.5px]'; + const favIconClass = 'translate-x-[-1px] translate-y-[0.5px]'; const items = useMemo(() => { const items: MoreMenuItem[] = [{ @@ -55,11 +56,20 @@ export default function AdminPhotoMenuClient({ ).then(() => revalidatePhoto?.(photo.id)), }); } + items.push({ + label: 'Download', + icon: , + href: photo.url, + hrefTargetBlank: true, + }); items.push({ label: 'Delete', icon: , action: () => { if (confirm(deleteConfirmationTextForPhoto(photo))) { diff --git a/src/components/more/MoreMenu.tsx b/src/components/more/MoreMenu.tsx index 39188b3e..7b8e493d 100644 --- a/src/components/more/MoreMenu.tsx +++ b/src/components/more/MoreMenu.tsx @@ -8,6 +8,7 @@ export interface MoreMenuItem { label: ReactNode icon?: ReactNode href?: string + hrefTargetBlank?: boolean action?: () => Promise | void } @@ -51,12 +52,13 @@ export default function MoreMenu({ 'shadow-lg dark:shadow-xl', )} > - {items.map(({ label, icon, href, action }) => + {items.map(({ label, icon, href, hrefTargetBlank, action }) => )} diff --git a/src/components/more/MoreMenuItem.tsx b/src/components/more/MoreMenuItem.tsx index 6fd4cf87..8b7ccc2d 100644 --- a/src/components/more/MoreMenuItem.tsx +++ b/src/components/more/MoreMenuItem.tsx @@ -10,11 +10,13 @@ export default function MoreMenuItem({ label, icon, href, + hrefTargetBlank, action, }: { label: ReactNode icon?: ReactNode href?: string + hrefTargetBlank?: boolean action?: () => Promise | void }) { const router = useRouter(); @@ -39,7 +41,11 @@ export default function MoreMenuItem({ onClick={e => { e.preventDefault(); if (href) { - startTransition(() => router.push(href)); + if (hrefTargetBlank) { + window.open(href, '_blank'); + } else { + startTransition(() => router.push(href)); + } } else { const result = action?.(); if (result instanceof Promise) {