fix: selection is unified across the tool
Signed-off-by: Varun Raj <varun@skcript.com>
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
import "yet-another-react-lightbox/styles.css";
|
||||
|
||||
import { IAsset } from '@/types/asset';
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from 'react'
|
||||
import Lightbox from 'yet-another-react-lightbox';
|
||||
import { Gallery } from "react-grid-gallery";
|
||||
import LazyGridImage from "../ui/lazy-grid-image";
|
||||
import Download from "yet-another-react-lightbox/plugins/download";
|
||||
import Video from "yet-another-react-lightbox/plugins/video";
|
||||
import { usePhotoSelectionContext } from '@/contexts/PhotoSelectionContext';
|
||||
|
||||
|
||||
interface AssetGridProps {
|
||||
@@ -16,10 +17,31 @@ interface AssetGridProps {
|
||||
onSelectionChange?: (ids: string[]) => void;
|
||||
}
|
||||
|
||||
export default function AssetGrid({ assets, isInternal = true, selectable = false, onSelectionChange }: AssetGridProps) {
|
||||
interface AssetGridRef {
|
||||
getSelectedIds: () => string[];
|
||||
selectAll: () => void;
|
||||
unselectAll: () => void;
|
||||
}
|
||||
|
||||
const AssetGrid = forwardRef<AssetGridRef, AssetGridProps>(({ assets, isInternal = true, selectable = false, onSelectionChange }, ref) => {
|
||||
const [index, setIndex] = useState(-1);
|
||||
const [selectedIds, setSelectedIds] = useState<string[]>([]);
|
||||
const [lastSelectedIndex, setLastSelectedIndex] = useState(-1);
|
||||
|
||||
// Use context for selection state
|
||||
const { selectedIds, updateContext } = usePhotoSelectionContext();
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
getSelectedIds: () => selectedIds,
|
||||
selectAll: () => {
|
||||
const allIds = assets.map((asset) => asset.id);
|
||||
updateContext({ selectedIds: allIds });
|
||||
onSelectionChange?.(allIds);
|
||||
},
|
||||
unselectAll: () => {
|
||||
updateContext({ selectedIds: [] });
|
||||
onSelectionChange?.([]);
|
||||
},
|
||||
}), [assets, selectedIds, updateContext]);
|
||||
|
||||
|
||||
const handleClick = (index: number, asset: IAsset, event: React.MouseEvent<HTMLElement>) => {
|
||||
@@ -35,8 +57,9 @@ export default function AssetGrid({ assets, isInternal = true, selectable = fals
|
||||
event.stopPropagation();
|
||||
const isPresent = selectedIds.includes(asset.id);
|
||||
if (isPresent) {
|
||||
setSelectedIds(selectedIds.filter((id) => id !== asset.id));
|
||||
onSelectionChange?.(selectedIds.filter((id) => id !== asset.id));
|
||||
const newSelectedIds = selectedIds.filter((id) => id !== asset.id);
|
||||
updateContext({ selectedIds: newSelectedIds });
|
||||
onSelectionChange?.(newSelectedIds);
|
||||
} else {
|
||||
const clickedIndex = images.findIndex((image) => {
|
||||
return image.id === asset.id;
|
||||
@@ -44,14 +67,15 @@ export default function AssetGrid({ assets, isInternal = true, selectable = fals
|
||||
if (event.shiftKey) {
|
||||
const startIndex = Math.min(clickedIndex, lastSelectedIndex);
|
||||
const endIndex = Math.max(clickedIndex, lastSelectedIndex);
|
||||
const newSelectedIds = images.slice(startIndex, endIndex + 1).map((image) => image.id);
|
||||
const allSelectedIds = [...selectedIds, ...newSelectedIds];
|
||||
const rangeSelectedIds = images.slice(startIndex, endIndex + 1).map((image) => image.id);
|
||||
const allSelectedIds = [...selectedIds, ...rangeSelectedIds];
|
||||
const uniqueSelectedIds = [...new Set(allSelectedIds)];
|
||||
setSelectedIds(uniqueSelectedIds);
|
||||
updateContext({ selectedIds: uniqueSelectedIds });
|
||||
onSelectionChange?.(uniqueSelectedIds);
|
||||
} else {
|
||||
setSelectedIds([...selectedIds, asset.id]);
|
||||
onSelectionChange?.([...selectedIds, asset.id]);
|
||||
const newSelectedIds = [...selectedIds, asset.id];
|
||||
updateContext({ selectedIds: newSelectedIds });
|
||||
onSelectionChange?.(newSelectedIds);
|
||||
}
|
||||
setLastSelectedIndex(clickedIndex);
|
||||
}
|
||||
@@ -93,7 +117,7 @@ export default function AssetGrid({ assets, isInternal = true, selectable = fals
|
||||
|
||||
const handleEsc = (event: KeyboardEvent) => {
|
||||
if (event.key === "Escape") {
|
||||
setSelectedIds([]);
|
||||
updateContext({ selectedIds: [] });
|
||||
onSelectionChange?.([]);
|
||||
}
|
||||
};
|
||||
@@ -122,4 +146,6 @@ export default function AssetGrid({ assets, isInternal = true, selectable = fals
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
})
|
||||
AssetGrid.displayName = "AssetGrid";
|
||||
export default AssetGrid;
|
||||
|
||||
@@ -73,7 +73,7 @@ export const getAssetGeoHeatmap = async (filters: IHeatMapParams) => {
|
||||
}
|
||||
|
||||
export const deleteAssets = async (ids: string[]) => {
|
||||
return API.delete(UPDATE_ASSETS_PATH, { ids });
|
||||
return API.delete(UPDATE_ASSETS_PATH, { ids, force: true });
|
||||
}
|
||||
|
||||
export interface IEmptyVideosParams {
|
||||
|
||||
@@ -150,6 +150,7 @@ export default function PotentialAlbums() {
|
||||
{contextState.selectedIds.length} Selected
|
||||
</p>
|
||||
<div className="flex items-center gap-2">
|
||||
{contextState.selectedIds.length === contextState.assets.length ? (
|
||||
<Button
|
||||
variant={"outline"}
|
||||
size={"sm"}
|
||||
@@ -161,8 +162,8 @@ export default function PotentialAlbums() {
|
||||
>
|
||||
Unselect all
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
) : (
|
||||
<Button
|
||||
variant={"outline"}
|
||||
size={"sm"}
|
||||
onClick={() =>
|
||||
@@ -170,10 +171,10 @@ export default function PotentialAlbums() {
|
||||
selectedIds: contextState.assets.map((a) => a.id),
|
||||
})
|
||||
}
|
||||
|
||||
>
|
||||
Select all
|
||||
</Button>
|
||||
)}
|
||||
<AlbumSelectorDialog onSelected={handleSelect} onSubmit={handleCreate} />
|
||||
<AssetOffsetDialog assets={selectedAssets} onComplete={handleOffsetComplete} />
|
||||
<div className="h-[10px] w-[1px] bg-zinc-500 dark:bg-zinc-600"></div>
|
||||
|
||||
@@ -22,6 +22,7 @@ export default function EmptyVideosPage() {
|
||||
const [assets, setAssets] = useState<IAsset[]>([])
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [errorMessage, setErrorMessage] = useState('')
|
||||
|
||||
|
||||
// Initialize filters from URL params or defaults
|
||||
const getInitialFilters = () => {
|
||||
|
||||
Reference in New Issue
Block a user