diff --git a/src/admin/AdminAppMenu.tsx b/src/admin/AdminAppMenu.tsx
index 799cef2b..27766084 100644
--- a/src/admin/AdminAppMenu.tsx
+++ b/src/admin/AdminAppMenu.tsx
@@ -57,20 +57,24 @@ export default function AdminAppMenu({
clearAuthStateAndRedirectIfNecessary,
} = useAppState();
+ const isSelecting = selectedPhotoIds !== undefined;
+
useEffect(() => {
- if (pathname !== PATH_GRID_INFERRED) {
+ if (isSelecting) {
setSelectedPhotoIds?.(undefined);
}
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [pathname, setSelectedPhotoIds]);
const appText = useAppText();
- const isSelecting = selectedPhotoIds !== undefined;
-
const isAltPressed = useIsKeyBeingPressed('alt');
const showAppInsightsLink = photosCountTotal > 0 && !isAltPressed;
+ const currentPageHasGrid = () =>
+ document.querySelector('[data-photo-grid]') !== null;
+
const sectionUpload: MoreMenuSection = useMemo(() => ({ items: [{
label: appText.admin.uploadPhotos,
icon: ,
- ...pathname !== PATH_GRID_INFERRED && {
- href: PATH_GRID_INFERRED,
+ ...!currentPageHasGrid() && {
+ href: `${PATH_GRID_INFERRED}?batch=true`,
},
action: () => {
if (isSelecting) {
@@ -192,7 +196,6 @@ export default function AdminAppMenu({
return { items };
}, [
- pathname,
appText,
isSelecting,
photosCountNeedSync,
diff --git a/src/admin/AdminBatchEditPanelClient.tsx b/src/admin/AdminBatchEditPanelClient.tsx
index c8894049..88928b08 100644
--- a/src/admin/AdminBatchEditPanelClient.tsx
+++ b/src/admin/AdminBatchEditPanelClient.tsx
@@ -8,8 +8,6 @@ import { clsx } from 'clsx/lite';
import { IoCloseSharp } from 'react-icons/io5';
import { useEffect, useRef, useState } from 'react';
import { TAG_FAVS, Tags } from '@/tag';
-import { usePathname } from 'next/navigation';
-import { PATH_GRID_INFERRED } from '@/app/path';
import PhotoTagFieldset from './PhotoTagFieldset';
import { tagMultiplePhotosAction } from '@/photo/actions';
import { toastSuccess } from '@/toast';
@@ -28,8 +26,6 @@ export default function AdminBatchEditPanelClient({
}) {
const refNote = useRef(null);
- const pathname = usePathname();
-
const {
isUserSignedIn,
selectedPhotoIds,
@@ -156,7 +152,7 @@ export default function AdminBatchEditPanelClient({
const shouldShowPanel =
isUserSignedIn &&
- pathname === PATH_GRID_INFERRED &&
+ document.querySelector('[data-photo-grid]') !== null &&
selectedPhotoIds !== undefined;
useEffect(() => {
diff --git a/src/cmdk/CommandKClient.tsx b/src/cmdk/CommandKClient.tsx
index d79fe6ca..bce31e16 100644
--- a/src/cmdk/CommandKClient.tsx
+++ b/src/cmdk/CommandKClient.tsx
@@ -644,12 +644,18 @@ export default function CommandKClient({
? appText.admin.batchEdit
: appText.admin.batchExitEdit,
annotation: ,
- path: selectedPhotoIds === undefined
- ? PATH_GRID_INFERRED
- : undefined,
- action: selectedPhotoIds === undefined
- ? () => setSelectedPhotoIds?.([])
- : () => setSelectedPhotoIds?.(undefined),
+ action: () => {
+ if (selectedPhotoIds === undefined) {
+ const hasGrid = document.querySelector('[data-photo-grid]') !== null;
+ if (!hasGrid) {
+ router.push(`${PATH_GRID_INFERRED}?batch=true`);
+ return;
+ }
+ setSelectedPhotoIds?.([]);
+ } else {
+ setSelectedPhotoIds?.(undefined);
+ }
+ },
}, {
label:
{appText.admin.appInsights}
diff --git a/src/photo/PhotoGrid.tsx b/src/photo/PhotoGrid.tsx
index 03b7acda..820f2a14 100644
--- a/src/photo/PhotoGrid.tsx
+++ b/src/photo/PhotoGrid.tsx
@@ -8,7 +8,8 @@ import AnimateItems from '@/components/AnimateItems';
import { GRID_ASPECT_RATIO } from '@/app/config';
import { useAppState } from '@/app/AppState';
import SelectTileOverlay from '@/components/SelectTileOverlay';
-import { ReactNode } from 'react';
+import { ReactNode, useEffect } from 'react';
+import { useRouter, useSearchParams } from 'next/navigation';
import { GRID_GAP_CLASSNAME } from '@/components';
export default function PhotoGrid({
@@ -21,7 +22,6 @@ export default function PhotoGrid({
staggerOnFirstLoadOnly = true,
additionalTile,
small,
- canSelect,
onLastPhotoVisible,
onAnimationComplete,
...categories
@@ -35,7 +35,6 @@ export default function PhotoGrid({
staggerOnFirstLoadOnly?: boolean
additionalTile?: ReactNode
small?: boolean
- canSelect?: boolean
onLastPhotoVisible?: () => void
onAnimationComplete?: () => void
} & PhotoSetCategory) {
@@ -46,68 +45,84 @@ export default function PhotoGrid({
isGridHighDensity,
} = useAppState();
+ const searchParams = useSearchParams();
+ const router = useRouter();
+
+ // Check for batch editing parameter on mount
+ useEffect(() => {
+ if (searchParams.get('batch') === 'true') {
+ setSelectedPhotoIds?.([]);
+ // Clean up the URL parameter
+ const url = new URL(window.location.href);
+ url.searchParams.delete('batch');
+ router.replace(url.pathname + url.search);
+ }
+ }, [searchParams, setSelectedPhotoIds, router]);
+
return (
- {
- const isSelected = selectedPhotoIds?.includes(photo.id) ?? false;
- return
-
+ {
+ const isSelected = selectedPhotoIds?.includes(photo.id) ?? false;
+ return
- {isUserSignedIn && canSelect && selectedPhotoIds !== undefined &&
- setSelectedPhotoIds?.(isSelected
- ? (selectedPhotoIds ?? []).filter(id => id !== photo.id)
- : (selectedPhotoIds ?? []).concat(photo.id),
+ >
+ }
- ;
- }).concat(additionalTile ? <>{additionalTile}> : [])}
- itemKeys={photos.map(photo => photo.id)
- .concat(additionalTile ? ['more'] : [])}
- />
+ {...{
+ photo,
+ ...categories,
+ selected: photo.id === selectedPhoto?.id,
+ priority: prioritizeInitialPhotos ? index < 6 : undefined,
+ onVisible: index === photos.length - 1
+ ? onLastPhotoVisible
+ : undefined,
+ }}
+ />
+ {isUserSignedIn && selectedPhotoIds !== undefined &&
+ setSelectedPhotoIds?.(isSelected
+ ? (selectedPhotoIds ?? []).filter(id => id !== photo.id)
+ : (selectedPhotoIds ?? []).concat(photo.id),
+ )}
+ />}
+ ;
+ }).concat(additionalTile ? <>{additionalTile}> : [])}
+ itemKeys={photos.map(photo => photo.id)
+ .concat(additionalTile ? ['more'] : [])}
+ />
+
);
};
diff --git a/src/photo/PhotoGridContainer.tsx b/src/photo/PhotoGridContainer.tsx
index 15c69fea..831d613d 100644
--- a/src/photo/PhotoGridContainer.tsx
+++ b/src/photo/PhotoGridContainer.tsx
@@ -19,7 +19,6 @@ export default function PhotoGridContainer({
animateOnFirstLoadOnly,
header,
sidebar,
- canSelect,
...categories
}: {
cacheKey: string
@@ -34,7 +33,6 @@ export default function PhotoGridContainer({
shouldAnimateDynamicItems,
setShouldAnimateDynamicItems,
] = useState(false);
-
const onAnimationComplete = useCallback(() =>
setShouldAnimateDynamicItems(true), []);
@@ -55,7 +53,6 @@ export default function PhotoGridContainer({
...categories,
animateOnFirstLoadOnly,
onAnimationComplete,
- canSelect,
}} />
{count > photos.length &&
}
}
diff --git a/src/photo/PhotoGridInfinite.tsx b/src/photo/PhotoGridInfinite.tsx
index cbc083dc..58da5065 100644
--- a/src/photo/PhotoGridInfinite.tsx
+++ b/src/photo/PhotoGridInfinite.tsx
@@ -14,7 +14,6 @@ export default function PhotoGridInfinite({
excludeFromFeeds,
canStart,
animateOnFirstLoadOnly,
- canSelect,
...categories
}: {
cacheKey: string
@@ -40,7 +39,6 @@ export default function PhotoGridInfinite({
canStart,
onLastPhotoVisible,
animateOnFirstLoadOnly,
- canSelect,
}} />}
);
diff --git a/src/photo/PhotoGridPageClient.tsx b/src/photo/PhotoGridPageClient.tsx
index e3f0c9ac..40062ff6 100644
--- a/src/photo/PhotoGridPageClient.tsx
+++ b/src/photo/PhotoGridPageClient.tsx
@@ -60,7 +60,6 @@ export default function PhotoGridPageClient({
}} />
}
- canSelect
/>
);
}